2013-01-02 47 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