C#中的Task.Delay()和Thread.Sleep()区别
C#中的Task.Delay()和Thread.Sleep()区别
一、简介
1.Thread.Sleep()是同步延迟,Task.Delay()是异步延迟。
2.Thread.Sleep()会阻塞线程,Task.Delay()不会。
3.Thread.Sleep()不能取消,Task.Delay()可以。
4.Task.Delay()实质创建一个运行给定时间的任务,Thread.Sleep()使当前线程休眠给定时间。
5.反编译Task.Delay(),基本上讲它就是个包裹在任务中的定时器。
6.Task.Delay()和Thread.Sleep()最大的区别是Task.Delay()旨在异步运行,在同步代码中使用Task.Delay()是没有意义的;在异步代码中使用Thread.Sleep()是一个非常糟糕的主意。通常使用await关键字调用Task.Delay()。
二、代码案例
案例一:Thread.Sleep()和Task.Delay()比较
代码:
static void Main(string[] args) { //阻塞,出现CPU等待... Task.Factory.StartNew(delegate { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ****** Start Sleep()******"); for (int i = 1; i <=10; i++) { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "******Sleep******==>" + i); Thread.Sleep(1000);//同步延迟,阻塞一秒 } Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ******End Sleep()******"); Console.WriteLine(); }); //不阻塞 Task.Factory.StartNew(() => { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======StartDelay()======"); for (int i =1; i <=10; i++) { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======Delay====== ==>" + i); Task.Delay(1000);//异步延迟 } Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======End Delay()======"); Console.WriteLine(); }); Console.ReadLine(); Console.ReadKey(); }
结果:
通过运行结果截图对比看出,Thread.Sleep()是同步延迟,Task.Delay()是异步延迟。
案例二:通过async/await实现Task.Delay()同步
代码:
//该段代码通过async/awatit实现“同步”Delay static void Main(string[] args) { Task.Factory.StartNew(async () => { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======Start Delay()======"); for (int i = 1; i <=10; i++) { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======Delay======" + i); await Task.Delay(1000); } Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ======End Delay()======"); }); Console.ReadKey(); }
结果:
运行结果可以看出,通过async/await实现了Task.Delay()同步
案例三:Task.Delay()取消
代码:
class Program { #region CancellationTokenSource cts = new CancellationTokenSource(); void PutThreadSleep() { Thread.Sleep(5000); } async Task PutTaskDelay() { try { await Task.Delay(5000, cts.Token);//需要.net4.5的支持 } catch (TaskCanceledException ex) { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff ==>") + ex.ToString()); } } private void ThreadSleep() { PutThreadSleep(); Console.WriteLine("Sleep : I am back"); } private async void TaskDelay() { await PutTaskDelay(); Console.WriteLine("Delay : I am back"); } private void CancelTaskDelay() { cts.Cancel(); } #endregion static void Main(string[] args) { #region Program p = new Program(); //不可取消 p.ThreadSleep(); //可取消 p.TaskDelay(); p.CancelTaskDelay(); #endregion Console.ReadKey(); } }
结果:
Task.Delay()取消,抛出异常信息。
三、总结
Task.Delay(),async/await和CancellationTokenSource组合起来使用可以实现可控制的异步延迟。
本文来自博客园,作者:码农阿亮,转载请注明原文链接:https://www.cnblogs.com/wml-it/p/14850246.html
技术的发展日新月异,随着时间推移,无法保证本博客所有内容的正确性。如有误导,请大家见谅,欢迎评论区指正!
开源库地址,欢迎点亮:
GitHub:https://github.com/ITMingliang
Gitee: https://gitee.com/mingliang_it
GitLab: https://gitlab.com/ITMingliang
建群声明: 本着技术在于分享,方便大家交流学习的初心,特此建立【编程内功修炼交流群】,为大家答疑解惑。热烈欢迎各位爱交流学习的程序员进群,也希望进群的大佬能不吝分享自己遇到的技术问题和学习心得!进群方式:扫码关注公众号,后台回复【进群】。