何时使用Task.Delay,何时使用Thread.Sleep?

有什么时候使用Task.Delay与Thread.Sleep的好规则?

  • 具体来说,是否有一个最低的价值来提供一个是有效的/高效率的?
  • 最后,由于Task.Delay在asynchronous/等待状态机上导致上下文切换,是否有使用它的开销?

当你想阻塞当前线程时使用Thread.Sleep

当需要逻辑延迟而不阻塞当前线程时使用Task.Delay

效率不应该是这些方法的首要考虑。 他们主要的现实世界使用是作为I / O操作的重试定时器,这些定时器大约为几秒而不是几毫秒。

Task.DelayThread.Sleep最大的区别是Task.Delay是用来运行asynchronous的。 在同步代码中使用Task.Delay没有任何意义。 在asynchronous代码中使用Thread.Sleep是一个非常糟糕的主意。

通常你会用await关键字调用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秒。 如果我们在Console.WriteLine之上移动await wait ,它将打印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"); } } 

尝试预测这将打印…

asynchronous:开始
asynchronous:运行0.0070048秒
同步:开始
asynchronous:运行5.0119008秒
asynchronous:完成
同步:运行5.0020168秒
同步:完成

此外,有趣的是, Thread.Sleep更准确,ms的准确性并不是真正的问题,而Task.Delay最less可以花费15-30ms。 这两个函数的开销相比,他们有毫秒的准确性(如果你需要更精确的话,使用Stopwatch类)。 Thread.Sleep仍然Task.Delay你的线程, Task.Delay释放它来做其他工作,而你等待。

如果当前线程被Thread.Sleep ,并且您使用Thread.Sleep并且正在执行,那么您可能会遇到ThreadAbortException 。 随着Task.Delay你总是可以提供取消令牌,并优雅地杀死它。 这就是我selectTask.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实际上使当前线程进入hibernate状态,这样你就会阻塞并浪费一个线程。 在asynchronous编程模型中,如果你想在延迟之后发生某些事情(延续),你应该总是使用Task.Delay()