半年前翻译了一系列很烂的异步编程文章,使用异步通用语:《将来的某个时候》我会重新翻译C#5.0中的Async。写在前面 异步编程在处理并发的时候用的越来越多。之所以说上面这句话,是为了区分多线程编程。各位司机都知道,其实异步编程的核心目标就是并发处理。但是常常会有一些无奈的说法和疑问,比如异步编程能否提高应用程序性能?他能缩短我花在任务上的时间吗?他会阻塞线程吗?如果线程没有阻塞,为什么断点不继续往下执行,兄弟!线程释放到哪里去了?我读书不多,别骗我,线程释放了,程序怎么跑?我前台用了Ajax,后台有必要用Async吗?可能作为司机的你看到最后一个问题,不得不摊开双手┑( ̄Д ̄)┍。多线程场景理解也许在某个时候,你想提高应用程序的执行速度,尽快得到结果。这时候绝对不要选择Async和Task。例如,你和你的妻子周末去超市购物。一进超市,发现每条结账队伍都有几十个人,于是用了多线程。你去排队,一个一个往前走,你的妻子在另一端购物。当你正要走到收银台时,你的妻子过来把购物车推给你,于是你结账回家。虽然这种行为很不文明,但是这是多线程,和异步编程无关。异步编程场景了解什么是异步编程,它能解决什么问题?你和你的妻子开了一家面包店,最初只有你们两个服务顾客。没想到新店开张这么火爆,每分钟来一个顾客,烤一个面包要两分钟。每次有客人来,你拿一块面包到后厨的烤箱烤,你和老婆还要花两分钟时间等各自的烤箱完成任务。但是在你等待的两分钟内,又来了两个顾客。照这样的速度下去,根本无法满足客户的需求!您已经发现了您和您妻子的问题:您和您妻子的两个线程都被烤箱占用的时间阻塞了!为了解决堵车的问题,你和老婆又买了两个烤箱,为了避免新顾客没有服务,每次送面包进烤箱,标记是哪个顾客的,马上退回,随时准备接收新的customers如果有顾客来,会马上接待,新面包会被送到另一个烤箱做标记,马上返回等待其他人上菜。面包烤好后,烤箱会发出“叮”的一声。注意,这个信号到来后,你不需要去后面的厨房烤箱取面包,而是你和你老婆不忙的人去取。这样处理后,高并发客户数对你来说就得心应手了。作为两个线程,你和你老婆可以以非阻塞的形式(不等待烤箱)不断地返回给客户。但是需要注意的是非阻塞的概念,他不让你的程序继续往下执行。就烤面包而言,你的一种烤法是这样的:1.把面包送到烤箱2.烤箱处理面包,给你结果3.拿到面包,发给客户。所以“非阻塞”的概念不允许你直接进入第三步。在非阻塞期间,你的方法中没有线程。这个方法还是要按照时间来等待,等待以后某个时间有信号叫醒你或者你老婆,然后这个方法恢复执行。因此,程序的执行时间不变,优化的是处理并发的能力和你的商店(服务器)的吞吐量。看代码就明白,异步编程应该应用于IO密集型场景,而不是CPU密集型场景。我们都知道线程是由CPU调度的。如果你有一个四核CPU,那么你的线程池中有四个线程,当进程的每个虚拟CPU分配一个线程时,性能将是最好的。它可以有效地使用CPU,而不会因为来回切换上下文而损失性能。想一想,在CPU密集型的场景下,CPU就是想占着你的线程,这时候异步编程是没有用的。但是在IO场景下,文件IO是从win32用户态API转到windows内核态,磁盘驱动在内核态运行。在此期间,您的线程在驱动程序的响应中被阻塞。在异步编程中,当你的操作被通知给磁盘驱动程序后,线程会立即返回,而不是等待。在未来某个时刻,驱动程序完成处理,处理结果放入CLR线程池队列中,状态机恢复。线程池方法中任意一个线程取到结果,方法继续向下执行。在网络IO中也是如此,只是驱动变成了网络驱动。请看下面的代码:publicstaticasyncTask
