Когда использовать 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()
Если вы хотите, чтобы что-то (продолжение) произошло после некоторой задержки.