Interrupt einen schlafenden Thread
Gibt es eine Möglichkeit zu Unterbrechen, einen schlafenden thread? Wenn ich code wie diesem.
while(true){
if(DateTime.Now.Subtract(_lastExecuteTime).TotalHours > 1){
DoWork();
_lastExecuteTime = DateTime.Now();
continue;
}
Thread.Sleep(10000) //Sleep 10 seconds
if(somethingIndicatingQuit){
break;
}
}
Ich bin zu wollen ausführen DoWork() jede Stunde. Also, ich würde gerne ein wenig schlafen länger als 10 Sekunden. Sagen überprüfen Sie alle 10 Minuten oder so. Allerdings, wenn mein Schlaf bis 10 Minuten, und ich töten will diesem hintergrund die Aufgabe, ich muss warten, bis der Schlaf wieder aufzunehmen.
Meine eigentliche code ist mit einem Gewinde versehen.ManualResetEvent Herunterfahren die Arbeit im hintergrund, aber mein Problem ist mit der ThreadSleep code. Ich poste mehr code, wenn nötig.
OK, ich werde hinzufügen ein bisschen mehr code komplett hier, wie ich denke, es wird einige Fragen beantworten.
private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private readonly ManualResetEvent _pauseEvent = new ManualResetEvent(true);
private Thread _backGroundWorkerThread;
//This starts our work
public void Start() {
_backGroundWorkerThread = new Thread(ExecuteWorker) {IsBackground = true, Name = WorkerName + "_Thread"};
_shutdownEvent.Reset();
_backGroundWorkerThread.Start();
}
internal void Stop() {
//Signal the shutdown event
_shutdownEvent.Set();
//Make sure to resume any paused threads
_pauseEvent.Set();
//Wait for the thread to exit
_backGroundWorkerThread.Join();
}
private void ExecuteWorker() {
while (true) {
_pauseEvent.WaitOne(Timeout.Infinite);
//This kills our process
if (_shutdownEvent.WaitOne(0)) {
break;
}
if (!_worker.IsReadyToExecute) {
//sleep 5 seconds before checking again. If we go any longer we keep our service from shutting down when it needs to.
Thread.Sleep(5000);
continue;
}
DoWork();
}
}
Mein problem ist hier,
_backGroundWorkerThread.Join();
Dieser wartet, bis der Thread.Schlafen in der ExecuteWorker() ausgeführt wird, in meinem hintergrund-thread.
Ich habe mehr von dem code. Die Klasse dieser code ist ein Kind von einem Elternteil der Klasse, die es schafft eine unendliche Anzahl von diesen. Der übergeordneten Steuerung Starten, Beenden, Anhalten und fortsetzen der diese Kind-Klassen und die Arbeit, die Sie tun. Es ist nicht eine einfache Sache zu Starten und zu Stoppen, die unterstützt werden muss.
was ist
_worker
hier?Nur eine Instanz einer Klasse, die scheduling-Logik. Es ist die Methode, IsReadyToExecute gibt einen booleschen Wert zurück. Die _worker ist nicht relevant zu dieser Frage.
InformationsquelleAutor Jeff Reddy | 2011-09-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Anstatt
Thread.Sleep
verwendenManualResetEvent.WaitOne
.Wo
terminate
ist einManualResetEvent
1 , können SieSet
auf Anfrage termination der Schleife.Update:
Mir ist nur aufgefallen, dass Sie sagten, Sie sind bereits mit
ManualResetEvent
zu kündigen, die Arbeit im hintergrund (ich nehme an, dass ist inDoWork
). Gibt es irgendeinen Grund, warum Sie nicht den gleichen MRE? Wenn das nicht möglich ist, es sollte sicherlich kein Problem sein mit einem anderen.Update 2:
Yeah, also statt
Thread.Sleep(5000)
imExecuteWorker
tun_shutdownEvent.WaitOne(5000)
statt. Es würde wie folgt Aussehen.1Es gibt auch eine
ManualResetEventSlim
Klasse .NET 4.0.Schön, du bist die erste, die ich stieß auf hier 🙂
InformationsquelleAutor Brian Gideon
Anstatt
Thread.Sleep
verwenden, können SieMonitor.Wait
mit einem timeout - und dann können SieMonitor.Pulse
aus einem anderen thread, um ihn zu aktivieren.Vergessen Sie nicht, müssen Sie die Sperre auf dem monitor, bevor Sie entweder
Wait
oderPulse
:Wenn Jon Skeet gibt Ihnen eine Antwort und Sie nicht die Arbeit, sind Sie der Umsetzung seiner Antwort falsch 🙂
Auch, Jon, haben Sie ersetzt meine endlos-Schleife --> while(true) mit Sperre(monitor). Nicht sicher, was das für mich tut. Überwachen Sie Auch.Pulse(); gib mir eine Ausnahme der Methode 'Puls' hat 1 parameter(s) butis aufgerufen mit 0 argument(en).
Dies ist eine große Antwort - mein Problem gelöst und es war die beste Monitor-Beispiel habe ich gefunden. Eine kleine Anfrage - Sie können Sie aktualisieren Sie Ihre Antwort zu klären, was die
monitor
variable ist? Könnte sein, offensichtlich für einige, aber ich musste ein wenig suchen. Danke!Ja tolle Antwort - dafür den untenstehenden link war auch sehr hilfreich: albahari.com/threading/...
InformationsquelleAutor Jon Skeet
Können Sie Thead.Unterbrechen zu wecken einen schlafenden thread. Es wird zu einem
ThreadInteruptedException
auf dem gesperrten thread, so dass es nicht die eleganteste oder effizienter Ansatz.Müssen Sie auch müde zu werden, die Unterbrechung eines thread in dieser Art und Weise unsicher ist. Es bietet keine Kontrolle über den Punkt, an dem das Gewinde ist abgebrochen, und daher sollte nicht verwendet werden, ohne sorgfältige Abwägung der Konsequenzen. Wie bereits in anderen Antworten schon, es ist weit besser, signal-basierte Verfahren zu kontrollieren, Wann der thread beendet wird, in einer kontrollierten Art und Weise.
Unsicher, auf welche Weise? Es wirft ein
ThreadInteruptedException
auf die blockierende thread. Vielleicht könnten Sie das noch näher erläutern? Ich denke mal du meinst, wenn es die Sperrung aus einem anderen Grund als den Schlaf?Unsicher, da Sie keine Möglichkeit haben, zu wissen, in welchem Zustand sich der thread unterbrochen wurde. Der thread nicht unterbrochen werden, auf "sichere Punkte" - es wird unterbrochen, wo immer es passiert zu sein. Dies könnte ein Punkt in der Zeit, wo der Staat die Anwendung nicht definiert ist oder falsch oder einfach nur falsch.
Fair point, ich werde eine Notiz, dass für die Referenz. Ich bin mir bewusst, dass es bessere alternativen gibt, die einfach nicht wollen, wiederholen die gleichen Antworten.
Thread.Interrupt
ist sicher. Es istThread.Abort
das ist nicht sicher.Interrupt
nur bewirkt, dass BCL wartende rufe (wieJoin
,Sleep
usw.) sofort wieder zurück. Es sei denn, Ihr code fehlerhaft ist dieThreadInterruptException
sollte get injiziert wird sicher Punkte, und Sie haben die volle Kontrolle. Nur achten Sie auf die Platzierung der Blockierung Anrufe, wenn Sie sich entscheiden, zu verwendenInterrupt
. Erneut, unterbrechen und Abbrechen von threads sind zwei sehr verschiedene Dinge!InformationsquelleAutor TheCodeKing
Können Sie nicht nur wickeln Ihre Faden.Schlaf-Teil in eine Schleife, so dass es eine Schleife 60-mal macht dann die anderen überprüfen? Natürlich all dies tut, ist trades aus einem einfachen wenn(somethingIndicatingQuit) gegen die DateTIme -, wenn der check, aber vorausgesetzt, vielleicht sind Sie echte code ist etwas teurer, mit einer zweiten Schleife konnten, bieten einige kleinere CPU-Einsparungen.
InformationsquelleAutor Tod
Wenn Sie wollen DoWork() jede Stunde, warum die Berechnung nicht die Anzahl der ms erforderlich ist, bis die nächste Stunde ist um und warten, dass die Zeit? Zum Abbrechen des sleep -, konnte man entweder eine wartemöglichkeit synchro Klasse, wie der monitor wie vorgeschlagen von @Jon Skeet, oder einfach nur ein flag im thread, der sagt, es zu verlassen, nachdem der Schlaf statt DoWork() und es einfach vergessen - entweder den thread töten, selbst, wenn die Zeit abgelaufen ist, oder Ihr Betriebssystem wird es töten auf app schließen, je nachdem, was zuerst kommt.
Rgds,
Martin
InformationsquelleAutor Martin James
warum nicht eine BlockingCollection? Ich sehe es als eine viel elegantere Lösung als die akzeptierte Antwort. ich auch nicht, dass es viel overhead im Vergleich zu den monitor.
hier ist, wie es zu tun:
initialisieren einer BlockingCollection als Mitglied:
statt
tun
Sie aufwachen können Sie diesen code verwenden
InformationsquelleAutor schmendrick