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%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 ...
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)
Thread
-Objekt 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.
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.
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
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.
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.
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.
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 >
Tags und Links c# multithreading sleep manualresetevent