2016-06-06 2 views
5

В однопоточном консольном приложении люди часто используют Thread.Sleep как ленивый способ приостановить приложение в течение некоторого времени.Выход программы спящего блока? Как это реализовано?

Этот вопрос вызвал интересные моменты о не использует этот подход: Why is Thread.Sleep so harmful

Однако кроме зная, что сон блокирует текущий поток, я не понимаю, как это работает - например, это делает максимум из ядра процессора в жесткая петля или действительно ли она приостанавливает поток?

Что еще важнее для меня, как консольное приложение реагирует на различные сценарии выхода приложений (CTRL-C, kill, кнопка закрытия окна), когда они попадают в середину сна? Будет ли он слепо продолжать выполнение до тех пор, пока сила ОС не убьет его, или он будет вести себя хорошо?

+4

Он просто рассказывает планировщик потоков операционной системы, чтобы не перенести нить на выполнение в течение заданного периода времени. Так что уверен, он «приостановлен». Консольные убийства реализуются ОС и просто завершают процесс. Независимо от того, какие нити в процессе делают, это не актуально, они перестают быть норвежским попугаем. –

+1

Для интересующихся вы можете увидеть [реализацию для 'Thread.Sleep() здесь) (http://referencesource.microsoft.com/#mscorlib/system/threading/thread.cs,5f1072b92dae1dd8). –

+0

Спасибо @HansPassant 'suspended' - это тот термин, который я хотел - поскольку Sheeo явно указывает, что поток приостановлен, а не приводит к вращению. Хорошая ссылка МП. –

ответ

5

Это скорее вопрос ОС, чем вопрос, связанный с C# /. NET, но я постараюсь ответить коротко.

Thread.Sleep не будет запирать ваш процессор, вместо этого он вызовет соответствующий механизм в базовой ОС, чтобы приостановить поток. В окнах эта функция описана здесь: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx

Использование этого обычного системного вызова: нить не может быть перенесена до истечения времени ожидания. Затем требуется принудительное уничтожение нити (или всего процесса).

Когда вы нажмете ctrl + c в cmd.exe, консоль порождает новый поток в каждом процессе, прикрепленном для обработки события (описано здесь: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682541(v=vs.85).aspx). Из-за этого ваша программа в целом по-прежнему будет «вести себя хорошо», когда вы нажмете ctrl + c, но ваша спящая нить сама по себе будет убита преждевременно.

2

Это исходный код Thread.Sleep метода:

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

Как мы видим, этот метод вызывает Thread.SleepInternal метод. В комментарии об этом мы можем прочитать, что этот метод приостанавливает текущий поток для тайм-аутов в миллисекундах. Затем мы можем прочитать, что если timeout == 0, этот метод заставляет поток отказаться от оставшейся части своего таймлиса, и если тайм-аут равен Timeout.Infinite, то тайм-аут не произойдет. Я рекомендую вам прочитать многопоточность и жизненный цикл приложения (в этом случае особенно приостановлено).

Ссылки:

+0

первая ссылка для Windows CE - возможно, не то, что использует OP – pm100

+0

@ pm100: Эти ссылки должны более или менее познакомить его с тем, как работает этот метод. – hubot

Смежные вопросы