本文版权归博客园和做者吴双本人共同全部。转载和爬虫必须在显要位置注明出处:http://www.cnblogs.com/tdwshtml
半年前翻译了一系列很糟糕的异步编程文章,用异步的经常使用语来讲:”在未来的某个时间“ 我还会从新翻译Async in C#5.0 http://www.cnblogs.com/tdws/p/5617242.htmlchrome
异步编程在处理并发方面被使用的愈来愈多,之因此说上面一句话,是为了区分多线程编程。各位司机都知道,实际上异步编程的核心目标正并发处理。可仍是常常有一些让人感到很无奈的说法和问题,好比说,异步编程能提升应用性能吗?他能缩短我处理任务的时间吗?他阻塞线程吗?若是不阻塞线程,断点为何不继续向下执行,个人哥!线程释放到哪儿去了?我都读书少你别骗我,线程都释放了程序怎么运行?前台我用了Ajax,后台使用Async有必要吗?也许若是做为司机的你看到最后一个问题,你只好摊手┑( ̄Д  ̄)┍。编程
也许在某些时刻,你想提升应用程序执行速度,尽快拿到一个结果。这个时候,应该选择的绝对不是Async和Task。打个比方说,你和你老婆周末去超市购物,刚一进超市门你发现结帐的每条队伍都几十人,因而你用到了多线程,你去排队,一我的一我的的往前走,你老婆在另外一头抓紧购物,在你快走到收银台的时候,你老婆来把购物车推给了你,因而大家直接结帐回家。虽然这种行为很不文明,但这就是多线程,和异步编程一点关系都没有。windows
那异步编程是什么状况,能解决什么问题呢?你和你老婆开了一家面包店,在初期只有你俩为顾客服务。没想到新店开张这么火,每分钟来一个顾客,而烤好一份面包须要两分钟。每来一位顾客你都拿着一片面包去后厨烤箱烤,而且你要和你老婆要花两分钟来等各自的烤箱完成任务。但是你等待的这两分钟,又来了两位顾客,着这样的速度下去,根本不能知足顾客们的需求呀!你已经发现你和你老婆的问题了:那就是你和你老婆这两条线程,都被烤箱花费的时间阻塞了!服务器
你和你老婆为了解决阻塞的问题,又买了两台烤箱,而且为了不新进顾客没人服务,每当你把面包送进烤箱后,标记其属于哪位顾客后当即返回,准备接待新的顾客,再有顾客光临,立马接待,并将新的面包送进另外一个烤箱并标记,并当即返回等待为其余人服务。在面包烤好后,烤箱会以“叮”一声,注意在这一信号到达后,并非必定要你去后厨烤箱取面包,而是你和你老婆谁不忙谁去取。这样处理后,高并发的顾客量,对你来讲就显得驾轻就熟了。你和你老婆作为两条线程,能够不断地以非阻塞的形式(不等烤箱),返回到顾客面前。可是须要注意的是不阻塞的概念,他不是让你的程序继续向下执行。就烤面包而言你的一个烤面包方法是这样的:网络
1.送入面包到烤箱 2.烤箱处理面包并给你结果 3.拿到面包送到顾客。因此说“不阻塞”的概念,不能让你直接作到第三步。在不阻塞期间,是没有线程在你的这个方法中的,这个方法仍是要按照时间等待,等待在将来某个时刻的信号唤醒你或者你老婆,此时该方法恢复执行。因此说程序执行的时间依然不变,获得优化的是处理并发的能力,你店里(服务器)的吞吐量。多线程
异步编程应当被适用于IO密集型场景,非CPU计算密集场景。你们知道线程受CPU调度,若是你是四核CPU,那么在你的线程池中,拥有四个线程,进程每一个虚拟CPU分配一个线程的时候,性能表现会最棒。既能高效运用CPU,又不用来回切换上下文损耗性能。你想一想,CPU密集的场景中,CPU就是要占用你的线程,在这个时候异步编程没有任何用处。然而在IO场景中,文件IO由win32用户模式的API到windows内核模式,在内核模式中操做磁盘驱动程序。这期间,你的线程阻塞在驱动程序的响应中。而异步编程中,你的操做通知到磁盘驱动程序后,线程当即返回而非等待,在未来的某个时刻,驱动程序处理结束,处理结果放入CLR线程池队列中,恢复状态机,线程池中任意线程取出结果,方法继续向下执行。在网络IO中也是如此,只不过驱动程序变成了网络驱动程序。请看以下代码:并发
public static async Task<string> DoSomeAsync() { using (var client = new HttpClient()) { var result = await client.GetAsync( "http://stackoverflow.com/questions/37991851/jenkins-configure-page-not-loading-version1-651-3-chrome-browser") .Result.Content.ReadAsStringAsync(); Console.WriteLine(result); //作一些其余操做 var res = 1 + 1; //---------------- return ""; } }
在编译的时候,DosomeAsync会被编译成一个状态机方法,状态机是什么先别管,你能够把它当成一个黑盒子。在遇到GetAsync的时候,在DoSomeAsync中返回一个Task任务对象,并由await在Task对象上传递用于恢复状态机的方法,至关于调用了ContinueWith().这个方法顾名思义,以xxx继续。而后线程从DoSomeAsync中返回。返回后干吗去了?该线程能够去处理其余事情了。在未来某一时刻,服务器向咱们发送了一个相应,网络驱动程序得知请求完毕,恢复该方法继续执行剩下的其余代码。配一张乱糟糟的图异步
在GC的垃圾清理执行过程当中,应用程序的全部线程都会被挂起,使用异步编程意味着在相同的并发量下,你可使用更少的线程来完成处理,额外带来的好处就是,所须要清理的线程是更少的。还有一点就是,所使用的线程少了,CPU线程切换也变得更少。async
若是个人点滴分享对你有点滴帮助,欢迎点击下方红色按钮关注,我将持续输出分享。也欢迎为我也为你本身点赞。
本文关键字,C# ASP.NET 异步编程 MVC Async await
额外阅读:异步编程最佳实践 https://msdn.microsoft.com/zh-cn/magazine/jj991977.aspx