Ich sehe, was Sie versuchen zu tun, und @ MarcGravell's Kommentar ist richtig, und auch was @mariosangiorgio sagt, ist wahr. Was Sie als Workaround tun können, verwenden Sie stattdessen einen Monitor Wait/Pulse
Mechanismus. Versuchen Sie Folgendes:
private readonly Queue<int> _queue = new Queue<int>();
private readonly object _locker = new object();
public void Thread1()
{
List<int> values = new List<int>();
int lastInput;
StringBuilder sb = new StringBuilder();
while (values.Count < 5)
{
lock (this._locker)
{
// wait until there is something in the queue
if (this._queue.Count == 0)
{
Monitor.Wait(this._locker);
}
// get the item from the queue
_queue.Dequeue(out lastInput);
// add the item to the list
values.Add(lastInput);
}
}
for (int i = 0; i < values.Count; i++)
{
sb.Append(String.Format("{0}\n", values[i]));
}
MessageBox.Show(sb.ToString());
}
private void button1_Click(object sender, EventArgs e)
{
Thread th1 = new Thread(Thread1);
th1.Start();
for (int i = 0; i < 8; i++)
{
lock (this._locker)
{
// put something in the queue
_queue.Enqueue(i);
// notify that there is something in the queue
Monitor.Pulse(this._locker);
}
}
}
Also, im Wesentlichen, was Sie tun werden ist eine Schleife aufrufen, die wird versuchen, und insgesamt 5 Elemente zu verbrauchen. Wenn der Consumer-Thread erkennt, dass keine Elemente in der Warteschlange zu konsumieren sind, wartet er, bis der Producer einige Elemente in die Warteschlange stellt. Sobald der Produzent die Artikel in die Warteschlange stellt, teilt er dem wartenden Consumer-Thread mit, dass er bereit ist zu gehen! Der Consumer-Thread wird dann die Blockierung aufheben und das Objekt verbrauchen, das sich in der Warteschlange befindet.
Jetzt zusätzlich, wenn Sie @ mariosangiorgio kommentieren, verwenden Sie tatsächlich eine gleichzeitige Sammlung. Also hat er recht, es gibt eigentlich keine Notwendigkeit zu blockieren. Wenn Sie also Ihr eigenes Blockierungs-/Entsperrexperiment durchführen möchten, können Sie mit meiner Implementierung fortfahren und einfach ein normales Queue
(nicht gleichzeitig) verwenden. Oder, wie @mariosangiorgio sagte, entfernen Sie einfach die AutoResetEvent
und lassen Sie die ConcurrentQueue
ihr Ding machen.
Denken Sie daran, dass wenn Sie nicht blockieren, Sie kontinuierlich die CPU durchlaufen und laufen lassen, bis etwas tatsächlich Dequeue
'd.
Haben Sie die "wichtigen" Hinweise im Abschnitt Anmerkungen [hier] (https://msdn.microsoft.com/en-us/library/system.threading.eventwaithandle.set (v = vs.110) gefunden? aspx)? Ich vermute, dass die meisten Ihrer 'Set()' Anrufe nichts tun –
Es sieht so aus, als ob Sie versuchen, Ihre eigene Implementation von [BlockingCollection] zu erstellen (https://msdn.microsoft.com/en-us/library/dd267312 (v = vs.110) .aspx), benutze einfach den eingebauten. –