何时使用Task.Delay,何时使用Thread.Sleep?
有什么时候使用Task.Delay与Thread.Sleep的好规则?
- 具体来说,是否有一个最低的价值来提供一个是有效的/高效率的?
- 最后,由于Task.Delay在asynchronous/等待状态机上导致上下文切换,是否有使用它的开销?
当你想阻塞当前线程时使用Thread.Sleep
。
当需要逻辑延迟而不阻塞当前线程时使用Task.Delay
。
效率不应该是这些方法的首要考虑。 他们主要的现实世界使用是作为I / O操作的重试定时器,这些定时器大约为几秒而不是几毫秒。
Task.Delay
和Thread.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()
。