2016-06-06 16 views
5

In einer single-threaded Konsole-Anwendung verwenden Menschen oft Thread.Sleep als eine faule Möglichkeit, die Anwendung für einige Zeit zu pausieren.Blockiert Sleep den Programm-Exit? Wie wird es umgesetzt?

Diese Frage aufgeworfen, interessante Punkte über diesen Ansatz nicht verwenden: Why is Thread.Sleep so harmful

jedoch außer, dass der Schlaf blockiert den aktuellen Thread zu wissen, ich verstehe nicht, wie es funktioniert - zum Beispiel tut es max aus dem CPU-Kern in eine enge Schleife oder pausiert es eigentlich den Faden?

Noch wichtiger für mich, wie reagiert eine Konsolen-App auf verschiedene App-Exit-Szenarien (STRG-C, Kill, Fenster schließen Schaltfläche), wenn mitten in einem Schlaf gefangen? Wird es blind weiter ausgeführt, bis das Betriebssystem es tötet, oder wird es sich gut verhalten?

+4

es einfach die Thread-Scheduler des Betriebssystems weist den Thread für die Ausführung für die angegebene Zeitspanne nicht neu planen. So sicher ist es "pausiert". Konsolen-Kills werden vom Betriebssystem implementiert und beenden den Prozess einfach. Was auch immer die Fäden in dem Prozess tun, ist nicht relevant, sie hören auf, norwegischer Papageienstil zu sein. –

+1

Für Interessierte können Sie die [Implementierung für 'Thread.Sleep()' hier] (http://referencesource.microsoft.com/#mscorlib/system/threading/thread.cs5f1072b92dae1dd8) sehen. –

+0

Danke @HansPassant 'suspended' ist der Begriff, den ich wollte - wie Sheeo ausdrücklich darauf hinweist, dass der Thread suspendiert ist, anstatt zu Spin-Lock zu führen. Nizza MP Referenz. –

Antwort

5

Dies ist eher eine Frage zum Betriebssystem als eine C# /. NET-bezogene Frage, aber ich werde versuchen und kurz zu beantworten.

Thread.Sleep sperrt nicht die CPU, sondern ruft den entsprechenden Mechanismus im zugrunde liegenden Betriebssystem auf, um den Thread zu sperren. Unter Windows wird diese Funktion hier beschrieben: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx

Mit diesem normalen Systemaufruf kann Ihr Thread nicht neu geplant werden, bis der Timeout abgelaufen ist. Das Erzwingen des Threads (oder des gesamten Prozesses) ist dann erforderlich.

Wenn Sie Strg + C in cmd.exe drücken, erzeugt die Konsole einen neuen Thread in jedem Prozess, der an das Ereignis gebunden ist (hier beschrieben: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682541(v=vs.85).aspx). Aus diesem Grund wird sich dein Programm als Ganzes immer noch "gut verhalten", wenn du Strg + C drückst, aber dein schlafender Thread selbst wird enden, wenn er vorzeitig getötet wird.

2

Dies ist Quellcode Thread.Sleep Methode:

[System.Security.SecuritySafeCritical] // auto-generated 
public static void Sleep(int millisecondsTimeout) 
{ 
    SleepInternal(millisecondsTimeout); 
    // Ensure we don't return to app code when the pause is underway 
    if(AppDomainPauseManager.IsPaused) 
     AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS(); 
} 

Wie wir diese Methode aufruft Thread.SleepInternal Methode sehen kann. Im Kommentar dazu können wir lesen, dass diese Methode den aktuellen Thread für Timeout-Millisekunden aussetzt. Als nächstes können wir lesen, dass, wenn timeout == 0 ist, diese Methode den Thread zwingt, den Rest seines Zeitfensters aufzugeben, und wenn das Zeitlimit gleich Timeout.Infinite ist, dann wird kein Zeitlimit auftreten. Ich empfehle Ihnen, über Multithreading und Anwendungslebenszyklus zu lesen (in diesem Fall besonders ausgesetzt).

Links:

+0

erster Link ist für Windows CE - wahrscheinlich nicht was der OP verwendet – pm100

+0

@ pm100: Diese Links müssen ihn mehr oder weniger vorstellen, wie es funktioniert. – hubot