Ich habe die Dokumentation dazu gelesen und glaube, dass ich es verstanden habe. Eine AutoResetEvent
wird zurückgesetzt, wenn der Code durchläuft event.WaitOne()
sondern ein ManualResetEvent
nicht.
Ist dies richtig?
Ich habe die Dokumentation dazu gelesen und glaube, dass ich es verstanden habe. Eine AutoResetEvent
wird zurückgesetzt, wenn der Code durchläuft event.WaitOne()
sondern ein ManualResetEvent
nicht.
Ist dies richtig?
Entnommen aus dem Buch C# 3.0 Nutshell, von Joseph Albahari
Threading in C# - Kostenloses E-Book
Ein ManualResetEvent ist eine Variante des AutoResetEvent. Es unterscheidet sich dadurch, dass es nicht automatisch zurückgesetzt wird, nachdem ein Thread durch einen WaitOne-Aufruf durchgelassen wurde, und funktioniert daher wie ein Tor: Der Aufruf von Set öffnet das Tor und lässt eine beliebige Anzahl von Threads, die WaitOne am Tor ausführen, durch; der Aufruf von Reset schließt das Tor, wodurch sich möglicherweise eine Warteschlange bis zum nächsten Öffnen des Tors ansammelt.
Man könnte diese Funktionalität mit einem booleschen "gateOpen"-Feld (deklariert mit dem Schlüsselwort "volatile") in Kombination mit "spin-sleeping" simulieren - wiederholtes Überprüfen des Flags und anschließendes Schlafen für eine kurze Zeitspanne.
ManualResetEvents werden manchmal verwendet, um zu signalisieren, dass eine bestimmte Operation abgeschlossen ist oder dass ein Thread seine Initialisierung abgeschlossen hat und bereit ist, Arbeit zu verrichten.
Ich habe einfache Beispiele erstellt, um das Verständnis der ManualResetEvent
対 AutoResetEvent
.
AutoResetEvent
: Nehmen wir an, Sie haben 3 Arbeiter-Threads. Wenn einer dieser Threads die WaitOne()
alle anderen 2 Threads stoppen die Ausführung und warten auf ein Signal. Ich nehme an, sie verwenden WaitOne()
. Es ist so: Wenn ich nicht arbeite, arbeitet niemand. Im ersten Beispiel können Sie sehen, dass
autoReset.Set();
Thread.Sleep(1000);
autoReset.Set();
Wenn Sie anrufen Set()
alle Threads arbeiten und warten auf ein Signal. Nach 1 Sekunde sende ich das zweite Signal und sie führen aus und warten ( WaitOne()
). Denken Sie daran, dass diese Jungs Fußballspieler sind, und wenn ein Spieler sagt, ich warte, bis der Trainer mich anruft, und die anderen warten, bis der Trainer ihnen sagt, dass sie weitermachen sollen ( Set()
)
public class AutoResetEventSample
{
private AutoResetEvent autoReset = new AutoResetEvent(false);
public void RunAll()
{
new Thread(Worker1).Start();
new Thread(Worker2).Start();
new Thread(Worker3).Start();
autoReset.Set();
Thread.Sleep(1000);
autoReset.Set();
Console.WriteLine("Main thread reached to end.");
}
public void Worker1()
{
Console.WriteLine("Entered in worker 1");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker1 is running {0}", i);
Thread.Sleep(2000);
autoReset.WaitOne();
}
}
public void Worker2()
{
Console.WriteLine("Entered in worker 2");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker2 is running {0}", i);
Thread.Sleep(2000);
autoReset.WaitOne();
}
}
public void Worker3()
{
Console.WriteLine("Entered in worker 3");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker3 is running {0}", i);
Thread.Sleep(2000);
autoReset.WaitOne();
}
}
}
In diesem Beispiel können Sie deutlich sehen, dass Sie beim ersten Klick auf Set()
wird er alle Threads loslassen, dann nach 1 Sekunde signalisiert er allen Threads zu warten! Sobald man sie wieder setzt, rufen sie trotzdem WaitOne()
werden sie weiterlaufen, weil man sie manuell aufrufen muss. Reset()
um sie alle aufzuhalten.
manualReset.Set();
Thread.Sleep(1000);
manualReset.Reset();
Console.WriteLine("Press to release all threads.");
Console.ReadLine();
manualReset.Set();
Es geht mehr um die Beziehung zwischen Schiedsrichtern und Spielern, denn unabhängig davon, ob einer der Spieler verletzt ist und auf ein Spiel wartet, werden andere weiterarbeiten. Wenn der Schiedsrichter sagt: "Warte" ( Reset()
), dann warten alle Spieler bis zum nächsten Signal.
public class ManualResetEventSample
{
private ManualResetEvent manualReset = new ManualResetEvent(false);
public void RunAll()
{
new Thread(Worker1).Start();
new Thread(Worker2).Start();
new Thread(Worker3).Start();
manualReset.Set();
Thread.Sleep(1000);
manualReset.Reset();
Console.WriteLine("Press to release all threads.");
Console.ReadLine();
manualReset.Set();
Console.WriteLine("Main thread reached to end.");
}
public void Worker1()
{
Console.WriteLine("Entered in worker 1");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker1 is running {0}", i);
Thread.Sleep(2000);
manualReset.WaitOne();
}
}
public void Worker2()
{
Console.WriteLine("Entered in worker 2");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker2 is running {0}", i);
Thread.Sleep(2000);
manualReset.WaitOne();
}
}
public void Worker3()
{
Console.WriteLine("Entered in worker 3");
for (int i = 0; i < 5; i++) {
Console.WriteLine("Worker3 is running {0}", i);
Thread.Sleep(2000);
manualReset.WaitOne();
}
}
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.