2016-06-06 20 views
5

In un'applicazione console a thread singolo, le persone utilizzano spesso Thread.Sleep come modo pigro per mettere in pausa l'applicazione per un po 'di tempo.Esce il programma di blocco del sonno? Come viene implementato?

Questa domanda ha sollevato interessanti spunti di non usare questo approccio: Why is Thread.Sleep so harmful

Tuttavia diverso sapendo che i blocchi del sonno il thread corrente, non capisco come funziona - per esempio lo fa max fuori il core della CPU in un ciclo stretto o mette effettivamente in pausa il thread?

Ancora più importante per me, in che modo un'app console risponde a vari scenari di uscita app (CTRL-C, kill, pulsante di chiusura della finestra) quando viene catturato nel mezzo di uno stato di sospensione? Continuerà ciecamente a eseguire l'esecuzione fino a quando il sistema operativo non lo forzerà, o si comporterà bene?

+4

Si dice semplicemente thread scheduler del sistema operativo di non riprogrammare il thread per l'esecuzione per il periodo di tempo specificato. Così sicuro, è "in pausa". Le uccisioni da console sono implementate dal sistema operativo e terminano semplicemente il processo. Qualunque cosa stiano facendo i thread nel processo non è rilevante, smettono di essere, in stile pappagallo norvegese. –

+1

Per chi fosse interessato, è possibile vedere [implementazione per 'Thread.Sleep()' qui] (http://referencesource.microsoft.com/#mscorlib/system/threading/thread.cs,5f1072b92dae1dd8). –

+0

Grazie a @HansPassant 'sospeso' è il termine che volevo - mentre Sheeo sottolinea esplicitamente che il thread è sospeso anziché portare allo spin-lock. Nizza riferimento MP. –

risposta

5

Questa è più una domanda di sistema operativo che una domanda correlata a C# /. NET, ma proverò a rispondere in modo sintetico.

Thread.Sleep non farà girare la CPU, ma chiamerà il meccanismo appropriato nel sistema operativo sottostante per sospendere il thread. Su Windows, questa funzione è descritta qui: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx

Utilizzando questa normale chiamata di sistema il thread non può essere riprogrammato fino a quando non è scaduto il timeout. È quindi necessario eliminare forzatamente il thread (o l'intero processo).

Quando si preme ctrl + c in cmd.exe, la console genera un nuovo thread in ogni processo collegato per gestire l'evento (Descritto qui: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682541(v=vs.85).aspx). Per questo motivo, il tuo programma nel suo complesso si "comporterà bene" anche quando premi ctrl + c, ma il tuo thread si finirà per essere ucciso prematuramente.

2

Questo è il codice sorgente di Thread.Sleep metodo:

[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(); 
} 

Come si può vedere questo metodo chiama Thread.SleepInternal metodo. Nel commento a questo proposito possiamo leggere che questo metodo sospende il thread corrente per i timeout in millisecondi. Successivamente, possiamo leggere che se timeout == 0, allora questo metodo costringe il thread a rinunciare al resto del suo timeslice e se il timeout è uguale a Timeout.Infinite allora non si verificherà alcun timeout. Vi consiglio di leggere sul multithreading e sul ciclo di vita dell'applicazione (in questo caso specialmente sospeso).

vicini:

+0

il primo collegamento è per Windows CE - probabilmente non quello che l'OP sta usando – pm100

+0

@ pm100: questo link deve più o meno presentargli come funziona il metodo. – hubot

Problemi correlati