Stellen Sie sich eine Konsolenanwendung vor, die einige Dienste in einem separaten Thread startet. Sie müssen lediglich warten, bis der Benutzer Strg + C drückt, um das System herunterzufahren.
Welcher der folgenden Wege ist der bessere?
static ManualResetEvent _quitEvent = new ManualResetEvent(false);
static void Main() {
Console.CancelKeyPress += (sender, eArgs) => {
_quitEvent.Set();
eArgs.Cancel = true;
};
// kick off asynchronous stuff
_quitEvent.WaitOne();
// cleanup/shutdown and quit
}
Oder dies mit Thread.Sleep (1):
static bool _quitFlag = false;
static void Main() {
Console.CancelKeyPress += delegate {
_quitFlag = true;
};
// kick off asynchronous stuff
while (!_quitFlag) {
Thread.Sleep(1);
}
// cleanup/shutdown and quit
}
c#
multithreading
sleep
manualresetevent
inOrbit
quelle
quelle
bool
nicht als deklariert istvolatile
, besteht außerdem die eindeutige Möglichkeit, dass nachfolgende Lesevorgänge_quitFlag
in derwhile
Schleife wegoptimiert werden, was zu einer Endlosschleife führt.Alternativ ist eine einfachere Lösung einfach:
quelle
Sie können dies tun (und den
CancelKeyPress
Ereignishandler entfernen ):Ich bin mir nicht sicher, ob das besser ist, aber ich mag die Idee,
Thread.Sleep
eine Schleife aufzurufen , nicht. Ich denke, es ist sauberer, Benutzereingaben zu blockieren.quelle
Ich bevorzuge die Verwendung der Application.Run
aus den Dokumenten:
quelle
Scheint, als würdest du es schwieriger machen als nötig. Warum nicht einfach
Join
den Thread, nachdem Sie ihm signalisiert haben, dass er aufhören soll?quelle
Es ist auch möglich, den Thread / das Programm basierend auf einem Abbruch-Token zu blockieren.
WaitHandle wird signalisiert, wenn das Token abgebrochen wird.
Ich habe diese Technik gesehen, die von Microsoft.Azure.WebJobs.JobHost verwendet wird, wobei das Token von einer Storno-Token-Quelle des WebJobsShutdownWatcher (einem Datei-Watcher, der den Job beendet) stammt.
Dies gibt eine gewisse Kontrolle darüber, wann das Programm enden kann.
quelle
CTL+C
weil sie einen lang laufenden Vorgang ausführt oder ein Daemon ist, der auch seine Arbeitsthreads ordnungsgemäß herunterfahren sollte. Sie würden dies mit einem CancelToken tun, und daher nutzt diese Antwort eineWaitHandle
bereits vorhandene Antwort , anstatt eine neue zu erstellen.Von den beiden ist der erste besser
denn im zweiten wird der Thread jede Millisekunde aufgeweckt und in einen teuren Betriebssystem-Interrupt umgewandelt
quelle
Console
Methoden, wenn Sie keine Konsole angeschlossen haben (weil das Programm beispielsweise von einem Dienst gestartet wird)Sie sollten es genauso machen, als würden Sie einen Windows-Dienst programmieren. Sie würden niemals eine while-Anweisung verwenden, sondern einen Delegaten. WaitOne () wird im Allgemeinen verwendet, während auf das Entsorgen von Threads gewartet wird - Thread.Sleep () - ist nicht ratsam - Haben Sie darüber nachgedacht, System.Timers.Timer zu verwenden, um dieses Ereignis zum Überprüfen des Herunterfahrereignisses zu verwenden?
quelle