我遇到了一个堆栈空异常。如果堆栈不为空(它有16个项目),这怎么可能发生呢?
我截取了错误的快照:
有人能解释一下吗?
我截取了错误的快照:
![Stack Empty Exception](https://istack.dev59.com/HWISR.webp)
在使用类似于 Stack<T>
的东西时,您必须同步访问。最简单的方法是使用lock
,这也让您可以将lock
用于同步本身;因此,弹出操作将如下所示:
int item;
lock (SharedMemory)
{
while (SharedMemory.Count == 0)
{
Monitor.Wait(SharedMemory);
}
item = SharedMemory.Pop();
}
Console.WriteLine(item);
lock (SharedMemory)
{
SharedMemory.Push(item);
Monitor.PulseAll(SharedMemory);
}
ConcurrentStack<T>
不是更简单吗? - AdamTryPop
。 - Marc Gravell栈已满,有16项?这怎么可能?!
在多线程环境下,这是完全可能的。
您的程序中是否使用了多个线程?如果是,SharedMemory
在进行任何更改之前应该被lock
。
SharedMemory
是一个Stack
,并且您正在使用多线程,如果您使用的是.Net 4,则应该使用:ConcurrentStack
编辑
在第一次编辑后,根据Quartermeister的评论,这是一个更简单的工作解决方案: int item;
var SharedMemory = new BlockingCollection<int>(new ConcurrentStack<int>());
// later in the Consume part
item = SharedMemory.Take(); // this will block until there is an item in the list
Console.WriteLine(item);
ConcurrentStack<>
只有 TryPop
方法,因此如果您想要一个阻塞弹出设置(如问题所述),使用该 API 并不能使其更简单。 - Marc Gravell
SharedMemory
不是线程安全的,并且你没有对其进行锁定。我猜得对吗? - RotemStack
/Stack<T>
没有被列为线程安全的,所以在不同的线程中访问.Count
/.Pop()
/.Push()
等内容时没有定义的行为,并且在没有看到执行Push()
的代码之前,无法评论可能的竞争场景。但最终的解决方案无论如何都是相同的:您需要进行同步,或使用一个是线程安全的容器。 - Marc Gravell