2013-01-02 8 views
6

Ich bekomme eine Stapel leer Ausnahme. Wie ist das möglich, wenn der Stapel nicht leer ist (er hat 16 Gegenstände)?Stack Empty Exception

bekam ich eine Momentaufnahme des Fehlers:

Stack Empty Exception

Kann jemand bitte erklären?

+2

Sie diesen Multithreading mit Tags versehen haben, um diesen Code Ich vermute, viele Threads zugreifen. Ich rate auch, dass 'SharedMemory' nicht Thread-sicher ist, und dass Sie es nicht sperren. habe ich recht? – Rotem

+1

Was ist 'SharedMemory' in diesem Kontext? und was ist "voll"? –

+0

Der Titel Ihrer Frage lautet "Stapel leer", Ihr erster Satz lautet "Stapel voll". Was ist hier wahr? –

Antwort

5

Sie Muss synchronisieren Zugriff, wenn etwas mit wie Stack<T>. Der einfachste Ansatz ist die Verwendung von lock, die dann auch die lock für die Synchronisation selbst verwendet; so wäre Pop:

int item; 
lock (SharedMemory) 
{ 
    while (SharedMemory.Count == 0) 
    { 
     Monitor.Wait(SharedMemory); 
    } 
    item = SharedMemory.Pop(); 
} 
Console.WriteLine(item); 

und Push wäre:

lock (SharedMemory) 
{ 
    SharedMemory.Push(item); 
    Monitor.PulseAll(SharedMemory); 
} 
+0

Würde nicht die 'ConcurrentStack ', wie von MBen vorgeschlagen, noch einfacher sein? – Adam

+0

@codesparkle wenn es eine blockierende 'Pop'-Methode hätte, vielleicht; aber das tut es nicht. Es hat nur "hol mir etwas, wenn etwas da ist", aka 'Trypop' –

+0

Das hat es für mich dank bro :); –

5

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

In Multithreading-Umgebung ist es sehr viel möglich.

Verwenden Sie mehr als einen Thread in Ihrem Programm? Wenn ja, sollte SharedMemorylock ed sein, bevor Sie Änderungen daran vornehmen.

+0

... und bevor Sie es abfragen! –

3

Wenn SharedMemory ein Stack ist, und Sie Multithreading verwenden und wenn Sie auf .Net 4 sind. Sie sollten verwenden: ConcurrentStack

bearbeiten

Nach meiner ersten Bearbeitung und einem großen Kommentar von Quartermeister dies eine einfachere Arbeitslösung:

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 <>' hat nur 'TryPop', also wenn es (wie in der Frage) ein Blocking-Pop Setup sein soll, wird es durch die Verwendung dieser API nicht einfacher. –

+0

@MarcGravell nicht das Blockieren-Pop sehen :) – MBen

+0

@MarcGravell noch, ist es nicht besser, den Code mit ConcurrentStack zu vereinfachen? – MBen