2016-05-29 19 views
0

Ich habe die folgenden Codes in C# für Konsumenten und Produzenten, die AutoResetEvent verwenden, aber sie funktionieren nicht, wenn mehrere Produzenten und ein Konsument vorhanden sind. Das Problem ist, dass der Verbraucher nicht alle Elemente in der Warteschlange konsumieren kann. Wenn ich debugge, merke ich, dass der Verbraucher nur ein Element entfernen kann und dann false zurückgibt und nicht mehr entfernen kann. Scheint das Problem ist in AutoResetEvent, aber ich kann nicht herausfinden, was falsch ist.Consumer/Producer mit AutoResetEvent

+0

Wenn Sie .NET 4.0 oder höher verwenden, möchten Sie möglicherweise BlockingCollection verwenden – Curious

Antwort

1

Das Problem bei der Verwendung eines Autoreset wie diese verwenden, ist, dass Sie kann Set() zweimal oder mehr aufrufen, aber WaitOne() nur einmal. Das Aufrufen von Set() auf einem ARE, das bereits signalisiert wird, wird immer fehlschlagen, das Element bleibt in der Warteschlange stecken. Ein Standard-Thread-Race-Bug. Sieht so aus, als könnten Sie es beheben, indem Sie die gesamte Warteschlange im Consumer leeren. Keine wirkliche Lösung, der Produzent kann immer noch vor dem Verbraucher rennen, Sie haben lediglich die Quote auf die einmonatige, nicht entbugbare Phase gesenkt.

SIND nicht möglich, kann nicht zählen. Verwenden Sie stattdessen einen Semaphore/Slim, der zeilensicher gezählt wurde. Oder verwenden Sie eine ConcurrentQueue, eine Klasse, die hinzugefügt wurde, um genau diese Art von Programmierproblem zu lösen.

1

Mithilfe von AutoResetEvent haben Sie das Programm so konzipiert, dass nur ein Verbraucher einen Artikel gleichzeitig konsumieren kann.

Wenn Sie mit dem ähnlichen Entwurf zum Aufkleben möchten, können Sie stattdessen Manual verwenden, das Ereignis zurücksetzen, wenn eines der Verbraucher Thread findet, dass es keine Produkte konsumiert werden, und das Ereignis ein, wenn die Der Produzenten-Thread weiß, dass mindestens ein Artikel konsumiert werden muss.

Sie können einen alternativen Entwurf mit Monitor-Klasse finden here

Sie auch die Verwendung von Blocking collection machen können, wenn Sie .NET 4.0 oder höher