Когда использовать Task.Delay, когда использовать Thread.Sleep?

Существуют ли правильные правила для использования Task.Delay против Thread.Sleep ?

  • В частности, существует ли минимальное значение для обеспечения эффективности / эффективности над другой?
  • Наконец, поскольку Task.Delay вызывает переключение контекста на конечный компьютер async / wait, есть ли накладные расходы на его использование?

Используйте Thread.Sleep если вы хотите заблокировать текущий stream.

Используйте Task.Delay если вы хотите логическую задержку, не блокируя текущий stream.

Эффективность не должна быть главной проблемой этих методов. Их первичное использование в реальном мире – это таймеры повтора для операций ввода-вывода, которые составляют порядка секунд, а не миллисекунд.

Самая большая разница между Task.Delay и Thread.Sleep заключается в том, что Task.Delay предназначен для асинхронного запуска. Не имеет смысла использовать Task.Delay в синхронном коде. ОЧЕНЬ плохая идея использовать Thread.Sleep в асинхронном коде.

Обычно вы вызываете Task.Delay() с ключевым словом Task.Delay() :

 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 , оно будет печатать Running за 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"); } } 

Попробуйте предсказать, что это будет печатать …

async: запуск
async: Запуск за 0.0070048 секунд
синхронизация: запуск
async: Запуск за 5.0119008 секунд
async: Готово
sync: Запуск за 5.0020168 секунд
sync: Done

Кроме того, интересно заметить, что Thread.Sleep гораздо точнее, точность ms не является проблемой, а Task.Delay может занимать минимум 15-30 мс. Накладные расходы по обеим функциям минимальны по сравнению с точностью до мс, которую они имеют (используйте Stopwatch если вам нужно что-то более точное). Thread.Sleep все еще связывает ваш Thread, Task.Delay отпустите его, чтобы выполнить другую работу, пока вы ждете.

если текущий stream убит и вы используете 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 – механизм ожидания по таймеру. Если вы посмотрите на источник, вы найдете ссылку на class Timer который отвечает за задержку. С другой стороны Thread.Sleep фактически заставляет текущий stream спать, таким образом вы просто блокируете и тратите один stream. В асинхронной модели программирования вы всегда должны использовать Task.Delay() если хотите что-то (продолжение) произойдет после некоторой задержки.

Это функционально эквивалентные операции – они просто создают паузу, но Task.Delay ждет.

Я нашел способ взломать Thread.Sleep , заставляя программу просыпаться периодически и делать события, если вы действительно должны ее использовать. Смотри ниже:

 // Pay attention every 1/10 sec to maintain some UI responsiveness while (val > 0) { Thread.Sleep(100); val = val - 100; Application.DoEvents(); if (val == x) { // You could do some conditional stuff here at specific times } } 

Замените val с желаемой задержкой в ​​миллисекундах. Чем больше вы понижаете значение Thread.Sleep тем больше будет реагировать программа. Кажется приемлемым для меня 100 мс. Лучше всего 50 мс.

  • Запуск задач в foreach Loop использует значение последнего элемента
  • Использование памяти в C #
  • Как остановить stream, созданный при реализации runnable-интерфейса?
  • Есть ли у блокировки xchg то же поведение, что и mfence?
  • Надуть представление в фоновом streamе
  • Как прервать Console.ReadLine
  • Как отладить многопоточное приложение в IntelliJ?
  • Async WebApi Thread.CurrentCulture
  • Можно ли использовать мьютекс в многопроцессорном случае в Linux / UNIX?
  • Зеленые темы против не зеленых нитей
  • kill -3, чтобы получить java thread dump
  • Interesting Posts
    Давайте будем гением компьютера.