Um zwischen ManualResetEvent oder Thread.Sleep () zu wählen

8

Ich bin mir nicht sicher, welche Strategie ich übernehmen soll ... Ich konzentriere mich darauf, dass meine Operation abgeschlossen wird, aber ich möchte auch Leistungsprobleme auf ein Minimum beschränken ... es gibt eine Methode namens Ausführen ( ) muss warten (synchron laufen), bis eine Operation abgeschlossen ist. Diese Operation findet in einem anderen Thread statt. Es gibt 2 Möglichkeiten, dasselbe zu implementieren ...

Mit ManualResetEvent

%Vor%

ODER

Mit einem einfachen while-Konstrukt

%Vor%

Welchen der beiden Ansätze sollte ich annehmen? Warum?

BEARBEITEN:

Q2. Was, wenn ich gerade ein leeres während Construct hatte? Was ist der Unterschied ...?

%Vor%

EDIT: (etwas, das ich vorher gesammelt habe)

Ссылка - In diesem Artikel heißt es, manualResets sind vergleichsweise langsamer, weil sie keinen verwalteten Code mehr haben zurück in ...

    
deostroll 04.11.2009, 19:06
quelle

7 Antworten

13

Aus Neugier, warum ManualResetEvent und nicht AutoResetEvent ? So oder so, gehen Sie mit dem OS primitive über einen Schlaf-Check-Schlaf-Ansatz.

Sie können auch eine Monitor lock verwenden (entweder explizit über Monitor.Enter und Monitor.Exit oder über einen lock block), aber der Ansatz sollte darauf basieren, was Sie tatsächlich tun; Wenn es ein Szenario von "Es gibt nur eines dieser Dinge und ich brauche exklusiven Zugriff", dann verwenden Sie eine Monitor lock. Wenn "Ich muss warten bis der andere Thread endet aus anderen Gründen als dem Ressourcenzugriff", dann verwende AutoResetEvent oder ManualResetEvent .

Die Vorschläge zur Verwendung von Thread.Join sind gut, wenn (und nur wenn)

  1. Sie haben Zugriff auf das andere Thread -Objekt
  2. Sie möchten nicht ausgeführt werden, bis der andere Thread endet .

Wenn beides nicht zutrifft (Sie haben keinen Zugriff, oder der andere Thread wird nicht beendet, wird nur eine "Entwarnung" signalisiert), dann ist Thread.Join nicht realisierbar.

Die schlechteste Option ist

while(!JobCompleted);

Dadurch wird der Prozessor mit unnötigen Überprüfungen der Variablen verbunden, ohne dass dazwischen eine Pause entsteht. Ja, es wird Ihren Thread blockieren, bis der Vorgang abgeschlossen ist, aber Sie werden die CPU-Auslastung (oder zumindest den Wert eines einzelnen Kerns) maximieren.

    
Adam Robinson 04.11.2009, 19:25
quelle
4

Das Ereignis macht die Prozessoren effizienter - Sie müssen den übergeordneten Thread nicht zum Abfragen aufwecken. Der Kernel weckt Sie, wenn das Ereignis ausgelöst wird.

    
nitzmahone 04.11.2009 19:10
quelle
2

Wenn Sie Zugriff auf das ursprüngliche Thread-Objekt haben oder diesen Zugriff erhalten können, verwenden Sie am besten Thread.Join() .

Edit: Auch wenn dies in einer GUI wie WinForms oder WPF geschieht, sollten Sie Hintergrundarbeiter

    
Randolpho 04.11.2009 19:09
quelle
2

Der Hauptnachteil bei der Verwendung von Thread.Sleep() besteht darin, dass Sie entscheiden, wie lange der Thread warten soll. Die Operation, auf die Sie warten, kann mehr oder weniger dauern, und im Allgemeinen ist es sehr schwierig, genau diese Zeit zu quantifizieren. Wenn der Thread zu lange schläft, nutzen Sie die Systemressourcen nicht optimal aus.

Um optimal zu sein, sollten Sie ManualResetEvent (oder AutoResetEvent ) verwenden, damit Ihr Thread wieder aufgenommen wird, sobald die abhängige Operation abgeschlossen ist.

    
Steve Guidi 04.11.2009 19:12
quelle
1

ManualResetEvent ist definitiv der richtige Weg.

Aus dem von Ihnen bereitgestellten Code-Snippet sieht es so aus, als würden Sie die Ausführung innerhalb Ihrer Execute-Methode delegieren. Wenn dies der Fall ist und Sie nur eine einzelne Aufgabe delegieren, warum delegieren Sie dann an einen anderen Thread, wenn Sie auf die Antwort warten müssen? Sie können den Prozess auch einfach synchron ausführen.

    
Mike 04.11.2009 19:33
quelle
1
  

manualresets sind vergleichsweise langsamer, weil sie nicht mehr in verwaltetem Code sind und wieder in ..

Sie sind wahrscheinlich langsamer als eine Warte / Impuls-Kombination , die Sie verwenden sollten hier meiner Meinung nach . Aber Manual/AutoResetEvents ist viel schneller als jede Thread.Sleep(x) , die du machst, selbst wenn du x = 1 wählst. Und selbst wenn Sie die Windows-Timer-Auflösung auf 1 ms senken.

  

Was ist, wenn ich nur ein leeres während Construct hatte? Was ist der Unterschied ...?

Dann dreht sich ein Kern um 100%, bis die Bedingung wahr wird, und stiehlt Zeit von anderen Threads, die stattdessen etwas Nützliches machen könnten, wie das Berechnen von Frames für "Angry Birds" - oder die CPU könnte einfach abkühlen und verzögert die negativen Auswirkungen der globalen Erwärmung für einige weitere Nanosekunden.

    
Eugene Beresovsky 23.08.2013 08:10
quelle
0

Beide Ansätze machen grundsätzlich dasselbe. Die while-Schleife ist jedoch etwas expliziter, da Sie die Ruhezeit angeben können. Obwohl ich die XXXResetEvent-Klassen verwenden würde, die in dem Szenario, in dem Sie arbeiten, verwendet werden sollen. Ich würde annehmen, dass die Threading-Klassen jetzt oder später mit robusterem Threading-Code implementiert werden, um vielleicht Thread-Affinität auf Multi-Core-Prozessoren zu behandeln >     

rocka 04.11.2009 19:18
quelle