Когда использовать Task.Задержка, когда использовать поток.Спать?

есть ли хорошее правило(ы) для того, когда использовать задач.Задержка и нить.Спи!--2-->?

  • в частности, существует ли минимальное значение для обеспечения эффективности/эффективности одного над другим?
  • наконец, начиная с задачи.Задержка вызывает контекстное включение асинхронного / ожидающего компьютера состояния, есть ли накладные расходы на его использование?

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");
    }
}

попытаться предсказать, что это будет печатать...

async: запуск
async: работает в течение 0.0070048 секунд
синхронизация: запуск
async: работает в течение 5.0119008 секунд
async: готово
синхронизация: работает в течение 5.0020168 секунд
синхронизация: готово

кроме того, интересно отметить, что Thread.Sleep гораздо точнее, точность ms На самом деле не проблема, в то время как Task.Delay смогите принять 15-30ms минимальное. Накладные расходы на обе функции минимальны по сравнению с точностью ms, которую они имеют (используйте Stopwatch класс, если вам нужно что-то более точное). 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 класс, который отвечает за задержку. С другой стороны!--2--> фактически делает текущий поток спящим, таким образом, вы просто блокируете и тратите один поток. В модели асинхронного программирования, вы всегда должны использовать Task.Delay() Если вы хотите, чтобы что-то (продолжение) произошло после некоторой задержки.


это функционально эквивалентные операции-они просто создают паузу, но задачу.Задержка неизбежна.