Unterbrechen Sie einen schlafenden Thread

8

Gibt es eine Möglichkeit, einen schlafenden Thread zu unterbrechen? Wenn ich einen ähnlichen Code habe.

%Vor%

Ich möchte DoWork () jede Stunde ausführen. Also würde ich gerne ein bisschen länger als 10 Sekunden schlafen. Sagen Sie alle 10 Minuten einen Scheck. Wenn ich jedoch den Ruhezustand auf 10 Minuten einstelle und diese Hintergrundaufgabe beenden möchte, muss ich warten, bis der Schlaf wieder aufgenommen wird.

Mein tatsächlicher Code verwendet ein Threading.ManualResetEvent, um die Hintergrundarbeit herunterzufahren, aber mein Problem ist mit dem ThreadSleep-Code. Ich kann bei Bedarf mehr Code posten.

OK, ich werde hier ein bisschen vollständiger Code hinzufügen, da ich denke, dass es einige der Fragen beantworten wird.

%Vor%

Mein Problem ist hier,

%Vor%

Dies wartet auf den Thread.Sleep in ExecuteWorker (), der in meinem Hintergrundthread ausgeführt wird.

    
Jeff Reddy 16.09.2011, 17:57
quelle

6 Antworten

11

Anstatt Thread.Sleep zu verwenden, verwenden Sie ManualResetEvent.WaitOne .

%Vor%

Wo terminate ein ManualResetEvent 1 ist, können Sie Set anfordern, um die Schleife zu beenden.

Aktualisierung:

Ich habe gerade bemerkt, dass Sie sagten, Sie benutzen bereits ManualResetEvent , um die Hintergrundarbeit zu beenden (ich nehme an, dass das in DoWork ist). Gibt es einen Grund, warum Sie nicht dasselbe MRE verwenden können? Wenn das nicht möglich ist, sollte es kein Problem geben, ein anderes zu verwenden.

Update 2:

Ja, statt Thread.Sleep(5000) in ExecuteWorker stattdessen _shutdownEvent.WaitOne(5000) . Es würde wie folgt aussehen.

%Vor%

1 Es gibt auch eine ManualResetEventSlim -Klasse in .NET 4.0.

    
Brian Gideon 16.09.2011, 18:27
quelle
32

Anstatt Thread.Sleep zu verwenden, kannst du Monitor.Wait mit einem Timeout verwenden - und dann kannst du Monitor.Pulse von einem anderen Thread verwenden, um es aufzuwecken.

Vergessen Sie nicht, dass Sie den Monitor vor dem Aufruf von Wait oder Pulse :

sperren müssen %Vor%     
Jon Skeet 16.09.2011 17:59
quelle
2

Sie können Thead.Interrupt verwenden, um einen schlafenden Thread aufzuwecken . Es wird ein ThreadInteruptedException auf dem blockierten Thread verursachen, also ist es nicht der eleganteste oder effizienteste Ansatz.

Sie müssen auch müde sein, dass das Unterbrechen eines Threads auf diese Weise unsicher ist. Es bietet keine Kontrolle über den Punkt, an dem der Thread abgebrochen wird, und sollte daher nicht ohne sorgfältige Abwägung der Konsequenzen verwendet werden. Wie bereits in anderen Antworten erwähnt, ist es weitaus besser, signalbasierte Techniken zu verwenden, um zu steuern, wann der Thread kontrolliert endet.

    
TheCodeKing 16.09.2011 18:22
quelle
0

Können Sie nicht einfach Ihren Thread.Sleep-Teil in eine Schleife wickeln, so dass er 60-mal durchläuft und dann die andere prüft? Natürlich handelt es sich hierbei um Trades von einem einfachen if (somethingIndicatingQuit) gegenüber dem DateTime, wenn man nachschaut, aber vorausgesetzt, dass echter Code etwas teurer macht, könnte eine zweite Schleife kleinere CPU-Einsparungen bringen .

    
Tod 16.09.2011 18:14
quelle
0

Wenn Sie jede Stunde mit DoWork () arbeiten möchten, warum berechnen Sie nicht die Anzahl der ms, die bis zur nächsten Stunde benötigt wird, und warten Sie auf diese Zeit? Um den Schlaf aufzuheben, könntest du entweder eine waitable Synchro-Klasse verwenden, wie den von @ Jon Skeet vorgeschlagenen Monitor, oder einfach eine Markierung im Thread setzen, die besagt, dass er nach dem Schlaf statt DoWork () beendet und einfach vergessen wird - entweder der Thread wird sich selbst töten, wenn die Zeit abgelaufen ist, oder Ihr Betriebssystem wird ihn beim Schließen der App beenden, je nachdem, was zuerst eintritt.

Rgds, Martin

    
Martin James 16.09.2011 18:27
quelle
0

Warum nicht eine BlockingCollection verwenden? Ich sehe es als einen viel eleganteren Ansatz als die angenommene Antwort. Ich denke auch nicht, dass es viel Overhead im Vergleich zum Monitor gibt.

Hier ist, wie es geht:

initialisiert eine BlockingCollection als Mitglied:

%Vor%

statt

%Vor%

tu dies

%Vor%

um es aufzuwecken, können Sie diesen Code verwenden

%Vor%     
schmendrick 11.04.2017 14:53
quelle

Tags und Links