写在前面

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关键字。异步函数会被编译器编译成复杂的程序结构,可以视其为一种状态机。不过需要提醒的是,如果不需要编写异步函数,那就用同步。

虽然异步编程已经变得非常简单,但是大家同样需要了解异步编程背后的理念以及原理,这有助于我们编写高性能高扩展的应用程序。

【憩园】C#并发编程之异步编程(一)的更多相关文章

  1. C#并发编程之异步编程2

    C#并发编程之异步编程(二)   写在前面 前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法.本篇文章将对async和await这两个关键字进行深入探讨,研究其中 ...

  2. C#复习笔记(5)--C#5:简化的异步编程(异步编程的基础知识)

    异步编程的基础知识 C#5推出的async和await关键字使异步编程从表面上来说变得简单了许多,我们只需要了解不多的知识就可以编写出有效的异步代码. 在介绍async和await之前,先介绍一些基础 ...

  3. .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)

    本文内容 异步编程类型 异步编程模型(APM) 参考资料 首先澄清,异步编程模式(Asynchronous Programming Patterns)与异步编程模型(Asynchronous Prog ...

  4. 【憩园】C#并发编程之异步编程(三)

      写在前面 本篇是异步编程系列的第三篇,本来计划第三篇的内容是介绍异步编程中常用的几个方法,但是前两篇写出来后,身边的朋友总是会有其他问题,所以决定再续写一篇,作为异步编程(一)和异步编程(二)的补 ...

  5. 【憩园】C#并发编程之异步编程(二)

    写在前面 前面一篇文章介绍了异步编程的基本内容,同时也简要说明了async和await的一些用法.本篇文章将对async和await这两个关键字进行深入探讨,研究其中的运行机制,实现编码效率与运行效率 ...

  6. 关于如何提高Web服务端并发效率的异步编程技术

    最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...

  7. 如何提高Web服务端并发效率的异步编程技术

    作为一名web工程师都希望自己做的web应用能被越来越多的人使用,如果我们所做的web应用随着用户的增多而宕机了,那么越来越多的人就会变得越来越少了,为了让我们的web应用能有更多人使用,我们就得提升 ...

  8. Java网络编程中异步编程的理解

    目录 前言 一.异步,同步,阻塞和非阻塞的理解 二.异步编程从用户层面和框架层面不同角度的理解 用户角度的理解 框架角度的理解 三.为什么使用异步 四.理解这些能在实际中的应用 六.困惑 参考文章 前 ...

  9. C#复习笔记(5)--C#5:简化的异步编程(异步编程的深入分析)

    首先,阐明一下标题的这个“深入分析”起得很惭愧,但是又不知道该起什么名字,这个系列也主要是做一些复习的笔记,供自己以后查阅,如果能够帮助到别人,那自然是再好不过了. 然后,我想说的是异步方法的状态机真 ...

随机推荐

  1. mapbox.gl源码解析——基本架构与数据渲染流程

    加载地图 Mapbox GL JS是一个JavaScript库,使用WebGL渲染交互式矢量瓦片地图和栅格瓦片地图.WebGL渲染意味着高性能,MapboxGL能够渲染大量的地图要素,拥有流畅的交互以 ...

  2. 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

  3. Java〜slf4日志框架的使用

    slf4日志可以支持注解的方式开启它,然后在使用时直接使用占位符,而不需要手动拼接字符串,这点在性能上也做到了最好. 一 build.gradle依赖项 compileOnly('org.projec ...

  4. 精读《V8 引擎 Lazy Parsing》

    1. 引言 本周精读的文章是 V8 引擎 Lazy Parsing,看看 V8 引擎为了优化性能,做了怎样的尝试吧! 这篇文章介绍的优化技术叫 preparser,是通过跳过不必要函数编译的方式优化性 ...

  5. 深入理解Linux内核 学习笔记(1)

    1.用户和用户组 每个用户是一个或多个用户组的一名成员,组由唯一的用户组标识符(user group ID)标识.每个文件的相关权限也恰好与一个组相对应. root为超级用户, 2.模块 为了达到微内 ...

  6. springcloud情操陶冶-springcloud config server(二)

    承接前文springcloud情操陶冶-springcloud config server(一),本文将在前文的基础上讲解config server的涉外接口 前话 通过前文笔者得知,cloud co ...

  7. [转]Date and String Function in BluePrism

    本文转自:https://www.codeproject.com/Articles/1247389/Date-and-String-Function-in-BluePrism This article ...

  8. [转]使用nodejs-koa2-mysql-sequelize-jwt 实现项目api接口

    本文转自:https://blog.csdn.net/yibowanbo/article/details/80521849 nodejs-koa2-mysql-sequelize-jwt技术栈:nod ...

  9. 用bat批处理程序通过DOS命令行删除所有的空文件夹

    用过gothub或者码云的同学都知道,不包含任何文件的空文件夹上传提交时不被允许的.当然你可以在空文件下创建.keep文件(或.gitkeep文件),然后就可以上传了. 但是如果空文件夹比较多,并且我 ...

  10. Autofac 和 Quartz.Net 自动注入的整合

    一:问题场景 在一次项目开发中,项目中已使用了Autofac.在新需求中要用到Quatrz.Net.在任务中使用注入方法,确始终无法使用注入的方法,经过千百次的度娘,终于找到了解决办法!吐槽下度娘真心 ...