2013-01-02 127 views
6

我收到堆栈空异常。如果堆栈不是空的(它有16个项目),这怎么可能?堆栈空异常

我得到了错误的快照:

Stack Empty Exception

可有人请解释一下吗?

+2

您已经标记了这个多线程所以我猜许多线程访问该代码。我也猜测'SharedMemory'不是线程安全的,而且你没有锁定它。我对吗? – Rotem

+1

在这种情况下'SharedMemory'是什么?什么是'全'? –

+0

您的问题标题显示“Stack empty”,您的第一句话显示“Stack full”。这里是什么? –

回答

5

必须同步接入使用的东西时,像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); 
} 
+0

不会使用MBen建议的'ConcurrentStack '更简单吗? – Adam

+0

@codesparkle如果它有阻塞的'Pop'方法,也许;但事实并非如此。它只有“如果有东西在那里,请给我一些东西”,又名'TryPop' –

+0

这对我感谢兄弟:); –

5

how is that possible the stack is full & has 16 items??!

在多线程环境中,它是非常有可能的。

您的程序中是否使用了多个线程?如果是,SharedMemory应在lock之前进行任何更改。

+0

...并在查询之前! –

3

如果SharedMemoryStack,并且因为您正在使用多线程并且您正在使用.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); 
+1

'ConcurrentStack <>'只有'TryPop',所以如果(按照问题)你想要一个阻止流行的设置,它并没有真正使用这个API更简单。 –

+0

@MarcGravell没有看到阻止流行:) – MBen

+0

@MarcGravell仍然,是不是更好地使用ConcurrentStack简化代码? – MBen