Ich habe die Dokumentation dazu gelesen und glaube zu verstehen. A wird AutoResetEvent
zurückgesetzt, wenn der Code durchlaufen event.WaitOne()
wird, a ManualResetEvent
jedoch nicht.
Ist das richtig?
c#
.net
multithreading
autoresetevent
manualresetevent
Ben McNiel
quelle
quelle
Antworten:
Ja. Es ist wie der Unterschied zwischen einer Mautstelle und einer Tür. Das
ManualResetEvent
ist die Tür, die manuell geschlossen (zurückgesetzt) werden muss. DasAutoResetEvent
ist eine Mautstelle, an der ein Auto vorbeifahren und automatisch schließen kann, bevor das nächste durchkommt.quelle
Stellen Sie sich vor, das wird
AutoResetEvent
ausgeführtWaitOne()
undReset()
als einzelne atomare Operation.quelle
Die kurze Antwort lautet ja. Der wichtigste Unterschied besteht darin, dass mit einem AutoResetEvent nur ein einziger wartender Thread fortgesetzt werden kann. Ein ManualResetEvent hingegen ermöglicht es Threads, mehrere gleichzeitig, fortzufahren, bis Sie anweisen, dass sie gestoppt werden sollen (Zurücksetzen).
quelle
Threading in C # - Kostenloses E-Book
Ein ManualResetEvent ist eine Variation von AutoResetEvent. Es unterscheidet sich darin, dass es nicht automatisch zurückgesetzt wird, nachdem ein Thread bei einem WaitOne-Aufruf durchgelassen wurde, und daher wie ein Gate funktioniert: Das Aufrufen von Set öffnet das Gate und lässt eine beliebige Anzahl von Threads zu, die WaitOne am Gate durchlässt. Durch das Aufrufen von Reset wird das Gate geschlossen, wodurch sich möglicherweise eine Warteschlange von Kellnern ansammelt, bis es das nächste Mal geöffnet wird.
Man könnte diese Funktionalität mit einem booleschen "gateOpen" -Feld (deklariert mit dem flüchtigen Schlüsselwort) in Kombination mit "Spin-Sleeping" simulieren - wiederholt das Flag überprüfen und dann für einen kurzen Zeitraum schlafen.
ManualResetEvents werden manchmal verwendet, um zu signalisieren, dass ein bestimmter Vorgang abgeschlossen ist oder dass die Initialisierung eines Threads abgeschlossen ist und zur Ausführung von Arbeiten bereit ist.
quelle
Ich habe einfache Beispiele erstellt, um das Verständnis von
ManualResetEvent
vs zu verdeutlichenAutoResetEvent
.AutoResetEvent
: Nehmen wir an, Sie haben 3 Worker-Thread. Wenn einer dieser ThreadsWaitOne()
alle anderen 2 Threads aufruft, wird die Ausführung gestoppt und auf das Signal gewartet. Ich gehe davon aus, dass sie verwendenWaitOne()
. Es ist wie; Wenn ich nicht arbeite, arbeitet niemand. Im ersten Beispiel können Sie das sehenWenn Sie aufrufen
Set()
, funktionieren alle Threads und warten auf das Signal. Nach 1 Sekunde sende ich ein zweites Signal und sie werden ausgeführt und warten (WaitOne()
). Denken Sie daran, dass diese Jungs Fußballspieler sind und wenn ein Spieler sagt, ich werde warten, bis der Manager mich anruft, und andere warten, bis der Manager ihnen sagt, dass sie fortfahren sollen (Set()
)In diesem Beispiel können Sie deutlich sehen, dass beim ersten Treffer
Set()
alle Threads losgelassen werden und nach 1 Sekunde alle Threads zum Warten aufgefordert werden! Sobald Sie sie erneut einstellen, unabhängig davon, ob sie im Haus anrufenWaitOne()
, werden sie weiter ausgeführt, da Sie manuell anrufen müssenReset()
, um sie alle zu stoppen.Es geht mehr um die Beziehung zwischen Schiedsrichter und Spieler, unabhängig davon, ob einer der Spieler verletzt ist oder ob das Warten auf das Spielen anderer weiterhin funktioniert. Wenn der Schiedsrichter wait (
Reset()
) sagt, warten alle Spieler bis zum nächsten Signal.quelle
autoResetEvent.WaitOne()
ist ähnlich wie
als atomare Operation
quelle
OK, normalerweise ist es keine gute Praxis, 2 Antworten im selben Thread hinzuzufügen, aber ich wollte meine vorherige Antwort nicht bearbeiten / löschen, da dies auf andere Weise hilfreich sein kann.
Jetzt habe ich unten ein viel umfassenderes und leicht verständliches Run-to-Learn-Konsolen-App-Snippet erstellt.
Führen Sie die Beispiele einfach auf zwei verschiedenen Konsolen aus und beobachten Sie das Verhalten. Sie werden dort eine viel klarere Vorstellung davon bekommen, was hinter den Kulissen passiert.
Manuelles Zurücksetzen
Auto Reset-Ereignis
quelle
AutoResetEvent verwaltet eine boolesche Variable im Speicher. Wenn die boolesche Variable false ist, wird der Thread blockiert, und wenn die boolesche Variable true ist, wird der Thread entsperrt.
Wenn wir ein AutoResetEvent-Objekt instanziieren, übergeben wir den Standardwert des booleschen Werts im Konstruktor. Unten finden Sie die Syntax zum Instanziieren eines AutoResetEvent-Objekts.
WaitOne-Methode
Diese Methode blockiert den aktuellen Thread und wartet auf das Signal eines anderen Threads. Die WaitOne-Methode versetzt den aktuellen Thread in einen Ruhezustand. Die WaitOne-Methode gibt true zurück, wenn sie das Signal empfängt. Andernfalls wird false zurückgegeben.
Die zweite Überladung der WaitOne-Methode wartet auf die angegebene Anzahl von Sekunden. Wenn es keinen Signal-Thread erhält, setzt es seine Arbeit fort.
Wir haben die WaitOne-Methode aufgerufen, indem wir die 2 Sekunden als Argumente übergeben haben. In der while-Schleife wartet es 2 Sekunden auf das Signal und setzt dann seine Arbeit fort. Wenn der Thread das Signal erhalten hat, gibt WaitOne true zurück und verlässt die Schleife und gibt das "Thread got signal" aus.
Methode einstellen
Die AutoResetEvent Set-Methode hat das Signal an den wartenden Thread gesendet, um seine Arbeit fortzusetzen. Unten finden Sie die Syntax zum Aufrufen der Set-Methode.
ManualResetEvent verwaltet eine boolesche Variable im Speicher. Wenn die boolesche Variable false ist, werden alle Threads blockiert, und wenn die boolesche Variable true ist, werden alle Threads entsperrt.
Wenn wir ein ManualResetEvent instanziieren, initialisieren wir es mit dem Standard-Booleschen Wert.
Im obigen Code initialisieren wir das ManualResetEvent mit einem falschen Wert. Dies bedeutet, dass alle Threads, die die WaitOne-Methode aufrufen, blockiert werden, bis ein Thread die Set () -Methode aufruft.
Wenn wir ManualResetEvent mit dem Wert true initialisieren, werden alle Threads, die die WaitOne-Methode aufrufen, nicht blockiert und können fortfahren.
WaitOne-Methode
Diese Methode blockiert den aktuellen Thread und wartet auf das Signal eines anderen Threads. Es gibt true zurück, wenn es ein Signal empfängt, andernfalls false.
Unten finden Sie die Syntax zum Aufrufen der WaitOne-Methode.
In der zweiten Überladung der WaitOne-Methode können wir das Zeitintervall angeben, bis der aktuelle Thread auf das Signal wartet. Wenn es innerhalb der internen Zeit kein Signal empfängt, gibt es false zurück und geht in die nächste Methodenzeile.
Unten finden Sie die Syntax zum Aufrufen der WaitOne-Methode mit Zeitintervall.
Wir haben 5 Sekunden in der WaitOne-Methode angegeben. Wenn das manualResetEvent-Objekt zwischen 5 Sekunden kein Signal empfängt, setzt es die Variable isSignalled auf false.
Methode einstellen
Diese Methode wird zum Senden des Signals an alle wartenden Threads verwendet. Set () -Methode Setzen Sie die boolesche Variable des ManualResetEvent-Objekts auf true. Alle wartenden Threads werden entsperrt und fahren fort.
Unten finden Sie die Syntax zum Aufrufen der Set () -Methode.
Methode zurücksetzen
Sobald wir die Set () -Methode für das ManualResetEvent-Objekt aufrufen, bleibt ihr Boolescher Wert true. Um den Wert zurückzusetzen, können wir die Reset () -Methode verwenden. Die Methode zum Zurücksetzen ändert den booleschen Wert in false.
Unten finden Sie die Syntax zum Aufrufen der Reset-Methode.
Wir müssen die Reset-Methode sofort nach dem Aufruf der Set-Methode aufrufen, wenn wir mehrmals ein Signal an Threads senden möchten.
quelle
Ja. Das ist absolut richtig.
Sie können ManualResetEvent als eine Möglichkeit sehen, den Status anzuzeigen. Etwas ist ein (Set) oder aus (Reset). Ein Ereignis mit einer gewissen Dauer. Jeder Thread, der auf diesen Status wartet, kann fortfahren.
Ein AutoResetEvent ist eher mit einem Signal vergleichbar. Ein One-Shot-Hinweis darauf, dass etwas passiert ist. Ein Ereignis ohne Dauer. Normalerweise, aber nicht unbedingt, ist das "Etwas", das passiert ist, klein und muss von einem einzelnen Thread verarbeitet werden - daher das automatische Zurücksetzen, nachdem ein einzelner Thread das Ereignis verbraucht hat.
quelle
Ja, das ist richtig.
Durch die Verwendung dieser beiden können Sie sich ein Bild machen.
Wenn Sie feststellen müssen, dass Sie mit einigen Arbeiten fertig sind und andere (Threads) darauf warten können, sollten Sie ManualResetEvent verwenden.
Wenn Sie gegenseitigen exklusiven Zugriff auf eine Ressource benötigen, sollten Sie AutoResetEvent verwenden.
quelle
Wenn Sie AutoResetEvent und ManualResetEvent verstehen möchten, müssen Sie nicht Threading, sondern Interrupts verstehen!
.NET möchte Low-Level-Programmierung so weit wie möglich heraufbeschwören.
Ein Interrupt wird in der Low-Level-Programmierung verwendet und entspricht einem Signal, das von Low zu High wurde (oder umgekehrt). In diesem Fall unterbricht das Programm seine normale Ausführung und bewegt den Ausführungszeiger auf die Funktion, die dieses Ereignis behandelt .
Das erste, was zu tun ist, wenn ein Interrupt passiert ist, ist das Zurücksetzen seines Status, da die Hardware folgendermaßen funktioniert:
Dies ist der Unterschied zwischen ManualResetEvent und AutoResetEvent.
Wenn ein ManualResetEvent auftritt und ich es nicht zurücksetze, kann ich es beim nächsten Mal nicht anhören.
quelle