何时使用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() 。