Когда использовать задачу.Задержка, когда использовать поток.Спать?
есть ли хорошие правила для того, когда использовать задач.Задержка и нить.Спи?
- в частности, существует ли минимальное значение для обеспечения того, чтобы один был эффективным/эффективным по сравнению с другим?
- наконец, начиная с задачи.Задержка вызывает контекстное переключение на асинхронный / ожидающий конечный автомат, есть ли накладные расходы на его использование?
5 ответов:
использовать
Thread.SleepЕсли вы хотите заблокировать текущий поток.использовать
Task.Delayкогда вы хотите логическую задержку без блокировки текущего потока.эффективность не должна быть первостепенной заботой с этими методами. Их основное использование в реальном мире-это повторные таймеры для операций ввода-вывода, которые составляют порядка секунд, а не миллисекунд.
самая большая разница между
Task.DelayиThread.SleepэтоTask.Delayпредназначен для запуска асинхронных. Не имеет смысла использоватьTask.Delayв синхронном коде. Это очень плохая идея, чтобы использоватьThread.Sleepв асинхронный код.обычно вы будете называть
Task.Delay()Сawaitключевые слова:await Task.Delay(5000);или, если вы хотите запустить какой-то код до задержки:
var sw = new Stopwatch(); sw.Start(); Task wait = Task.Delay(5000); Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds); await wait;думаю, что это будет печатать? Работает в течение 0.0070048 секунд. Если мы переместим
await waitвышеConsole.WriteLineвместо этого, он будет печатать работает в течение 5.0020168 секунд.давайте посмотрим на разницу с
Thread.Sleep:class Program { static void Main(string[] args) { Task wait = asyncTask(); syncCode(); wait.Wait(); Console.ReadLine(); } static async Task asyncTask() { var sw = new Stopwatch(); sw.Start(); Console.WriteLine("async: Starting"); Task wait = Task.Delay(5000); Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds); await wait; Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds); Console.WriteLine("async: Done"); } static void syncCode() { var sw = new Stopwatch(); sw.Start(); Console.WriteLine("sync: Starting"); Thread.Sleep(5000); Console.WriteLine("sync: Running for {0} seconds", sw.Elapsed.TotalSeconds); Console.WriteLine("sync: Done"); } }попытаться предсказать, что это будет печатать...
асинхронность: начиная с
асинхронность: работает в течение 0.0070048 секунд
синхронизация: запуск
асинхронность: работает в течение 5.0119008 секунд
асинхронно: готово
синхронизация: работает в течение 5.0020168 секунд
синхронизации: сделаликроме того, интересно отметить, что
Thread.Sleepгораздо точнее, точность ms На самом деле не проблема, в то время какTask.Delayсмогите принять 15-30МС минимальное. Накладные расходы на обе функции минимальны по сравнению с точностью ms, которую они имеют (useStopwatchкласс, если вам нужно что-то более точное).Thread.Sleepвсе еще связывает вашу нить,Task.Delayотпустите ее, чтобы сделать другую работу, пока вы ждете.
если текущий поток будет убит, и вы используете
Thread.Sleepи он выполняется, то вы можете получитьThreadAbortException. СTask.Delayвы всегда можете предоставить токен отмены и изящно убить его. Вот одна из причин, по которой я бы выбралTask.Delay. см http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspxЯ также согласен, что эффективность не имеет первостепенного значения в этом случае.
Я хочу кое-что добавить. Вообще-то,
Task.Delayэто механизм ожидания на основе таймера. Если вы посмотрите на источник вы найдете ссылку наTimerкласс, который отвечает за задержку. С другой стороныThread.Sleepна самом деле делает текущий поток в спящий режим, таким образом, вы просто блокируете и тратите один поток. В асинхронной модели программирования вы всегда должны использоватьTask.Delay()Если вы хотите, чтобы что-то (продолжение) произошло после некоторой задержки.
это функционально эквивалентные операции-они просто создают паузу, но задачу.Задержка вполне ожидаема.
Comments