在 web 服务器上,.NET Framework 维护用于处理 http://ASP.NET 请求的线程池。当请求到达时,将调度池中的线程以处理该请求。如果以同步方式处理请求,则处理请求的线程将在处理请求时处于繁忙状态,并且该线程无法处理其他请求。
在启动时看到大量并发请求的 web 应用中,或具有突发负载(其中并发增长突然增加)时,使 web 服务调用异步会提高应用程序的响应能力。异步请求与同步请求所需的处理时间相同。 如果请求发出需要两秒钟时间才能完成的 web 服务调用,则该请求将需要两秒钟,无论是同步执行还是异步执行。但是,在异步调用期间,线程在等待第一个请求完成时不会被阻止响应其他请求。因此,当有多个并发请求调用长时间运行的操作时,异步请求会阻止请求队列和线程池的增长。
await关键字不会阻塞线程直到任务完成。它将方法的其余部分注册为任务的回调,并立即返回。当await的任务最终完成时,它将调用该回调,并因此在其中断时继续执行方法。
简单来说:就是使用同步方法时,线程会被耗时操作一直占有,直到耗时操作完成。而使用异步方法,程序走到await关键字时会立即return,释放线程,余下的代码会放进一个回调中(Task.GetAwaiter()的UnsafeOnCompleted(Action)回调),耗时操作完成时才会回调执行,所以async/await是语法糖,其本质是一个状态机。
那是不是所有的action都要用async/await呢?
不是。
一般的磁盘IO或者网络请求等耗时操作才考虑使用异步,不要为了异步而异步,异步也是需要消耗性能的,使用不合理会适得其反。