从其它线程发起后,在一个新的单独线程上运行的操作。发起异步操作的线程不必等待异步操作完成。

简单来说,正常程序执行是从上到下逐语句执行,这就叫同步。

比如当你写同步程序的时候,你的代码中需要先后执行两个非常耗时间的操作,暂且把这两个操作取名了A 和 B,按照同步的方式,那就必须先执行A 等A执行完(假如耗费时间10秒)然后再执行B(假如耗时15秒),这样总共就耗时25秒。这个时候假如A和B能够同时执行,异步。 那么只需要耗时15秒就能够执行完。

如果代码里面也没有网络或 I/O 绑定操作,异步对你代码基本没有什么性能的提升。

首先,从别人的博客中找到几条对理解异步很有帮助的问题,贴在这里

疑问一:await会阻塞当前线程,等异步线程干完活了再跑?

不会阻塞。当前线程会一直跑进异步方法里,直到遇到要新开一个线程干活时就返回继续跑。此时,新线程在那里干活,主线程干完活就忙其他事去了。新线程干完活,回来await的地方把接下来的活继续干了。

疑问二:async+await 和同步执行有什么好处,都是要一个线程干活,一条龙干到底不好吗,非得自己干到一半交给另一个线程去干,别人干活不用开销吗?

这个问题的关键就是有些IO事情真的不需要CPU派一个线程去干,去了也干不了。比如读写文件,以往同步方法时,派一个线程去读写点东西的时候,这个线程肯定是等在那的,读写这个事情是硬盘去做的,线程就是个使者,告诉硬盘要做哪些事就行,硬盘干完活就告诉线程,线程拿着结果开心地继续干下面的活。那异步就是线程通知硬盘去读写后自己就回去该干嘛干嘛去,不必等在硬盘家门口等消息。硬盘读写的时候,这个线程是非阻塞的,可以干其他活,提高效率。硬盘读写完,会通知CPU,叫他派一个线程来拿结果,(如果框架是单线程的,那还是这个线程过来)这个线程拿到结果后会继续执行之前那个线程未干完的活,至于上下文信息,底层会交代好,不在这里讨论,太深。这个IO事情有很多,比如访问数据库,请求网络等。

然后,异步方法理解起来的一个难点其实就是异步等待,理解了异步等待的执行和原理,其实就能理解异步方法比同步方法的性能优化在哪个地方了。

其实很简单,最重要的是你要搞懂无阻塞异步等待的概念,因为正确的webapi的async await的作用就是这一个,可以无阻塞异步等待。

如果你要阻塞线程,那么你也就不需要强行异步了。如果你不需要等待,那用Task.Run那样跑掉就完了,不需要去await。

也就是说一个是同步的,一个是加了async await的异步代码,他们在代码结构上一模一样,仅仅是多了无阻塞异步等待。

那么无阻塞异步等待是什么意思呢? 最基本的意思就是不占用自己资源的去等待一个异步跑完,比如基本不占用任何线程

那么这样异步之后的好处是什么呢? 比如 你把线程数量限制在1,这样就会非常明显,你有一个action,里面CPU密集的东西很少,加一个等待10秒钟啥也不干,一下子访问10次, 异步基本10秒后就同时完成了这个方法,他们在等待时就把这个线程空出来了。而阻塞版执行完需要100秒,阻塞时就真的阻塞了,把别的请求也阻塞了。 我们平时不会没事儿等待10秒钟,但是我们访问网络等他回复,查询数据库等数据回来,访问文件等数据时,其实都是啥也没做的在那里等待,而其实这些都是让系统IO去做事情,我无所事事,所以windows下有了IOCP,其他平台下会用一个循环去处理。

最终的好处其实比较微妙,就是减少对线程池里线程数量的占用,听起来貌似用处不大,但是博客园当时就遇到了线程猛增一时间创造不出那么多线程导致卡顿宕机,之后用了async await后基本线程池没压力的事情。

也就是说,如果是单次请求,或者并发量不大的时候,同步等待和异步等待可能从时间和调试的时候,程序员是无感的,但是,如果并发量大的话,那么在await的时候,主线程可以处理await之前或者之后的其他方法,这样从总执行时长是有优化的。

这里有一个小demo来验证了上边说的情况:这里边说的情况是,Test方法被循环调用,只有eee被打印的时候是耗时操作,eee之前的操作很简单不耗时,这样就会被先执行,eee在线程内执行,不会阻塞主线程。

.net core api 在actionfilter 设置用户信息 .net core await_多线程

上边的例子中await的是一个Task.Run 理论上可以理解成一个线程,那么为了排序多线程对异步方法的影响,我把这个方法改掉了,执行的结果跟之前也是一致的,如图:

.net core api 在actionfilter 设置用户信息 .net core await_主线程_02

 我觉得通过引用的别人的疑问,和上边的这个简单的demo,会对大家理解异步方法的运行和优势了。

总结起来就是说,如果是webapi的话使用异步方法来处理的话,在硬件不改变的情况下,异步实现会比同步实现并发量或者说吞吐量会大。对进一步压榨服务器的cpu资源是有益处的。