C#并发编程之异步编程(一)

写在前面

C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不须要深入了解异步编程的底层原理,就能够写出十分优美而又代码量极少的代码。若是使用得当,你能够写出具备并行化而且性能较高的程序,可是同时也增长了对异步编程理解的复杂度,毕竟在C#5.0里,你已经看不到异步编程具体是如何实现的了,须要花费额外的经历去研究探索。数据库

使用异步编程,使得咱们释放了启动它的线程,也使得资源的占有量降低。更重要的是,有些特殊线程,好比UI线程,在运行的时候只能启动一个,若是没有快速响应,页面将会出现卡顿现象。本文只会基于.NET FX4.5及之后的版本进行讲解,以前的版本若是要实现异步编程,须要从nuget上面下载Microsoft.Bcl.Async,不过我仍是建议你,若是想要在系统中大量使用编写异步代码,仍是要是使用.NET FX4.5或更高的版本编程

异步编程主要分为基于事件的异步模式(EAP)和基于任务的编程模式(TAP)。EAP在调用方法以前当即注册事件,它具备void返回类型,但这种模式比较混乱,它将本来的一个方法分拆成两个方法。本系列主要关注TAP编程而不涉及EAP编程。异步

异步编程是什么

异步关键字

做为C#5.0中新增的重量级功能,异步功能是指程序在进行长时间操做完成后,须要继续执行的操做的一种方法,在编程过程当中,会感受这些异步代码和同步或者阻塞代码相似,可是实际上,编译器会将标识为异步的方法进行进一步的转换,是的代码能够实现真正的异步编程。它主要以两个关键字的形式功能你们使用:async

  • async
  • await

如下以一个经过EF Core查询用户信息的代码片断,这个例子没有什么特殊的地方异步编程

public Users GetUserInfo(string userId)
{
    using (UserDbContext db = new UserDbContext())
    {
        var user = db.Users.FirstOrDefault(p => p.UserId = userId);
        return user;
    }
}

接下来咱们看看异步的实现代码函数

public async Task<Users> GetUserInfoAsync(string userId)
{
    using (UserDbContext db = new UserDbContext())
    {
        var user = await db.Users.FirstOrDefaultAsync(p => p.UserId = userId);
        return user;
    }
}

以上两段代码看起来很是的相似,可是仔细看却有明显的不一样。异步方法上多了一个async的标识,同时返回值User,被标识成了Task<Users>,同时在进行数据库查询的时候,使用到了await。这里提早说一下await关键字,当编译器看到await关键字的时候,会截断方法,便于线程调度。简单点说,就是当调用线程运行到FirstOrDefaultAsync时,查询开始,但不是在当前线程,在新的线程里面,咱们查询完数据库后,根据须要作进一步处理,好比,若是原线程UI线程,它将返回以继续处理用户的其余操做(这里很是相似回调方式),不然的话,这个线程就直接被释放了。这段可能比较抽象,会在以后的系列里进一步讲解。性能

为了更好的进行异步编程,咱们须要在方法签名后面追加Async,这是一种异步编程的规约,也但愿你们遵照。spa

虽然异步编程对系统以及用户的体验很是的有帮助,但若是对异步编程不甚了解,可能会发生一些使人感到诡异的问题,并且这些问题可能经过debug方式也很可贵到解决。线程

异步执行流程

一、想象一下,在现实世界中,一个顾客到电脑专卖店买东西,就是那种拿了就走的场景。若是店铺只有一我的,在与顾客1没有结算完成以前,对顾客2的请求,只能暂时放置一下。相信你们在现实世界中,确定会遇到相似的状况,心情可能也很不爽,若是不是很迫切,多是再看看,换一家店,若是比较着急,就会一直催,而后也不必定会有回应。debug

以下图所示

二、有一天,老板请了几个伙计帮忙搬电脑,在顾客1没有结算完成以前,老板就能够接住顾客2的需求,并经过信息系统或者大吼一嗓子的方式,让电脑准备顾客2的电脑。同时,电脑把顾客1的电脑搬到前台,由老板去跟顾客结算,整个的流程就显得体验度很高,顾客也不会被忽略,卖出去的东西也多了不少,不过等待仍是要等的。

以下图所示

 

写在后面

本文主要介绍了异步编程的基础,经过以上介绍,咱们知道要建立一个异步函数,首先须要用async去修饰一个方法,同时返回值类型必须是Task或者Task<T>,固然在使用UI控制器时间处理的时候是可使用async void的。在方法内部,须要使用await关键字。异步函数会被编译器编译成复杂的程序结构,能够视其为一种状态机。不过须要提醒的是,若是不须要编写异步函数,那就用同步。

虽然异步编程已经变得很是简单,可是你们一样须要了解异步编程背后的理念以及原理,这有助于咱们编写高性能高扩展的应用程序。

相关文章
相关标签/搜索