欢迎来到.NET绿叶网!

mvc async await异步编程

2016-07-01 mvc异步编程 async await

在mvc中如果要用纯异步请不要使用async和await,可以直接使用Task.Run。

在mvc中使用async和await可以让系统开新线程处理Task的代码,同时不必等Task执行结束,就可以同时运行Task之后的代码,加快效率。

要注意的是:如果使用async和await,系统虽然可以同时处理多个事务,但客户端(浏览器)不会有响应,依然要等到所有代码全部执行完毕(包括异步的代码)才能正常响应。

什么场景下需要异步操作?

在因为磁盘io或网络io而导致的任务执行时间长的时候应该使用异步操作,如果任务执行时间长是因为cpu的消耗则应使用同步操作(此时异步操作不会改善任何问题)

异步原理是什么?

在 Web 服务器上,.NET Framework 维护一个用于服务 ASP.NET 请求的线程池(以下把 .NET Framework 维护的用于服务 ASP.NET 请求的线程池称作为“特定线程池”)

同步操作时,如果特定线程池利用满了,则不会再提供服务

异步操作时:一个请求过来,特定线程池出一个线程处理此请求。启动一个非特定线程池中的另一个线程处理异步操作,此时处理此请求的线程就会空出来,不会被阻塞,它可以继续处理其它请求。异步操作执行完毕后,从特定线程池中随便找一个空闲线程返回请求结果。

实际工作中,async和await我们可以用于类似用户上传头像、上传照片这种的耗时较长的功能中,我们可以在边上传照片时边处理数据库的其他事务。

而纯异步则多用于时间较长,而无需结果实时看反馈给用户的操作,例如:管理在后台备份数据库、清理垃圾文件等。

如果async和await的异步方法是有返回值的,而且主方法中又要使用这个返回值,那么将不会实现多个异步方法同时执行,要等异步结果后才继续执行,相当于异步并未起到多程序同时处理事务的目的。这仅是对于Web或控制台程序而言的,如果对于Winform则有大大的不同,因为Winform如果使用异步时界面是可以响应的。

Web中异步更多的是用来实现大量IO操作,或大量调用WCF、WebService时使用。

示例:

[HttpGet]

[Route("api/QRCodes")]

public async Task<IHttpActionResult> Get() {

    var member = this.GetCurrentMember();

    var qr = await GetMemberQRCode(member);

    return this.Success(new {

        QRCode = qr.QRCode,

        LastModifiedAt = qr.LastModifiedAt

    });

}

private async Task<MemberQRCode> GetMemberQRCode(Auction.Models.Membership.Member member) {

    //本方法用以创建二维码

}

以上例子中,其实响应时间并没有因为异步而减少,因为客户端(浏览器)不会有响应,依然要等到所有代码全部执行完毕(包括异步的代码)才能正常响应。但是异步可以空出线程池,增加接口吞吐量。

使用async异步编程时,请注意如下事项:

async void函数只能在UI Event回调中使用。

async void函数中一定要用try-catch捕获所有异常,否则会很容易导致程序崩溃。

async void类型的lambda表达式非常隐蔽,并且容易在无意中编写出来,尤其需要注意。

不要忽视CS4014告警,更不要为了消除CS4014告警而改用async void函数。

确实无需等待的async Task函数用我前面写的扩展函数IgnorCompletion消除这个告警。

注册TaskScheduler.UnobservedTaskException事件,记录Task中未处理异常信息,方便分析及错误定位。