585 Stimmen

Was ist der Unterschied zwischen ManualResetEvent und AutoResetEvent in .NET?

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?

995voto

Dan Goldstein Punkte 22942

Ja. Das ist wie der Unterschied zwischen einer Mautstelle und einer Tür. Die ManualResetEvent ist die Tür, die manuell geschlossen (zurückgesetzt) werden muss. Die AutoResetEvent ist eine Mautstelle, die ein Auto durchlässt und sich automatisch schließt, bevor das nächste durchfahren kann.

139voto

Michael Damatov Punkte 14513

Man stelle sich vor, dass die AutoResetEvent führt aus. WaitOne() y Reset() als eine einzige atomare Operation.

El AutoResetEvent garantiert außerdem, dass nur eine Warteschlange.

62voto

Martin Brown Punkte 23597

Die kurze Antwort lautet: Ja. Der wichtigste Unterschied ist, dass ein AutoResetEvent nur einen einzigen wartenden Thread weiterlaufen lässt. Ein ManualResetEvent hingegen erlaubt die Fortsetzung von Threads, sogar von mehreren gleichzeitig, bis Sie ihm sagen, dass es aufhören soll (Reset).

36voto

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.

21voto

Teoman shipahi Punkte 45327

Ich habe einfache Beispiele erstellt, um das Verständnis der ManualResetEventAutoResetEvent .

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.com

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.

Powered by:

X