写在前面
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
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, 这是一种异步编程的规约, 也希望大家遵守.
虽然异步编程对系统以及用户的体验非常的有帮助, 但如果对异步编程不甚了解, 可能会发生一些令人感到诡异的问题, 而且这些问题可能通过 debug 方式也很难得到解决.
异步执行流程
1, 想象一下, 在现实世界中, 一个顾客到电脑专卖店买东西, 就是那种拿了就走的场景. 如果店铺只有一个人, 在与顾客 1 没有结算完成之前, 对顾客 2 的请求, 只能暂时放置一下. 相信大家在现实世界中, 肯定会遇到类似的情况, 心情可能也很不爽, 如果不是很迫切, 可能是再看看, 换一家店, 如果比较着急, 就会一直催, 然后也不一定会有回应.
如下图所示
2, 有一天, 老板请了几个伙计帮忙搬电脑, 在顾客 1 没有结算完成之前, 老板就可以接住顾客 2 的需求, 并通过信息系统或者大吼一嗓子的方式, 让电脑准备顾客 2 的电脑. 同时, 电脑把顾客 1 的电脑搬到前台, 由老板去跟顾客结算, 整个的流程就显得体验度很高, 顾客也不会被忽略, 卖出去的东西也多了很多, 不过等待还是要等的.
如下图所示
写在后面
本文主要介绍了异步编程的基础, 通过以上介绍, 我们知道要创建一个异步函数, 首先需要用 async 去修饰一个方法, 同时返回值类型必须是 Task 或者 Task<T>, 当然在使用 UI 控制器时间处理的时候是可以使用 async void 的. 在方法内部, 需要使用 await 关键字. 异步函数会被编译器编译成复杂的程序结构, 可以视其为一种状态机. 不过需要提醒的是, 如果不需要编写异步函数, 那就用同步.
虽然异步编程已经变得非常简单, 但是大家同样需要了解异步编程背后的理念以及原理, 这有助于我们编写高性能高扩展的应用程序.
以上为本篇文章的主要内容, 希望大家多提提意见, 如果喜欢记得点个赞哦
来源: https://www.cnblogs.com/edison0621/p/10542953.html