深入理解Async/Await

C# 5 Async/Await 语法特性,极大地简化了异步编程,但我们知道,异步编程的基本原理并没有发生根本改变。也就是说,当一些复杂的东西看起来很简单时,它通常意味着有一些有趣的事情在背后发生。在计算机程序设计语言领域,我们把这些本身很复杂但看起来很简单的语言特性称为语法糖,通常情况下,我们并不需要深入理解语法糖是怎么被一层一层包裹起来的,但是,最近我在使用.NET Core实现MySQL协议过程中,需要实现一个Awaitable Socket,所以我需要知道Async/Await背后到底发上了什么?

编译器重写

我们通过写一个非常简单的控制台应用程序,一层一层地剥开C#编译器实现的 Async/Await 语法糖。

namespace AsyncAwaitInDepth{class Program{static void Main(string[] args){ }static async int Method(){return 1;}}}

编译上面的C#代码,会出现CS1983 The return type of an async method must be void, Task or Task<T>错误,即编译器告诉我们,异步方法仅限于三个不同的返回类型︰

  • void

  • Task

  • Task

再修改一下代码,让编译器编译通过:

    }}

使用ILSpy或者Reflector看看编译器干了什么:

上面的代码可以发现,aynce/await 代码被C#编译器重写了,编译器通过使用三个Builder和动态生成的StateMachine替换掉了我们的代码,而把我们的代码整理到StateMachine的MoveNext()方法内部,三个Builder是:

  • AsyncVoidMethodBuilder

  • AsyncTaskMethodBuilder

  • AsyncTaskMethodBuilder

撇开这三个Builder的内部实现,从接口角度看,他们长得很像,我们只看看AsyncTaskMethodBuilder<T>接口:l


C#编译器动态生成的StateMachine实现了IAsyncStateMachine接口:

  • AsyncVoidMethodBuilder

  • AsyncTaskMethodBuilder

  • AsyncTaskMethodBuilder

我们自己代码中的await Task.Delay(5);表达式,在StateMachine的MoveNext()方法内部被替换成awaiter = Task.Delay(5).GetAwaiter();,然后通过IsCompleted属性判断是否需要启动一个新的线程去执行,最后通过awaiter.GetResult();获取结果,或者是给Builder设置异常builder.SetException(exception);

Awaitables and Awaiters

在.NET中,我们知道XtableXter是一个一对的概念,比如IEnumerable<T>IEnumerator<T>,上面的代码,我们发现Task,Task<TResult>是可以被awaited的,他们是awaitable,可以通过其GetAwaiter()方法得到awaiter:

awaitableGetAwaiter()可以是实例方法,也可以是扩展方法。该方法返回的是一个awaiter,该awaiter必须实现INotifyCompletion接口,可选实现ICriticalNotifyCompletion接口,同时,必须提供一个名为IsCompleted bool 属性, 必须提供public TResult GetResult()方法。


自定义awaitableawaiter对象

我们费了那么大的劲,终于弄清楚了 Async/Await 背后到底发上了什么,做到了知其然知其所以然,因此,我们可以实现自己的awaitableawaiter对象:

最后,借用《C# in Depth》作者Job Skeet的一句话与大家共勉:

I like knowing how a feature works before I go too far using it

我们团队正在招聘几个小伙伴【招聘】腾讯(深圳)新增招聘互联网金融.NET开发,我们是有追求的团队,不满足CRUD,我们探索.NET的深度技术,不仅仅是完成业务,我们追求极致,如果你也是这样,欢迎加入我们。


原文地址:http://www.xyting.org/2017/02/28/understand-async-await-in-depth.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/326675.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c mysql 编码_mysql编码转换 mysql编码设置详解

查看mysql编码&#xff1a;一、 代码示例:mysql> show variables like character_set_%;------------------------------------------------------| variable_name | value |------------------------------------------------------| character_set_client | latin1 || cha…

2015蓝桥杯省赛---java---B---2(立方变自身)

题目 立方变自身 分析 简单枚举 i^3 99之后&#xff0c;数字越大&#xff0c;数字之和越不可能等于其自身。 代码 package com.atguigu.TEST;public class Demo01 {private static int ans;public static void main(String[] args) { // 6for (int i 1; i < 99; i) {…

Spring 由构造函数自动装配

转载自 Spring 由构造函数自动装配 Spring 由构造函数自动装配 这种模式与 byType 非常相似&#xff0c;但它应用于构造器参数。Spring 容器看作 beans&#xff0c;在 XML 配置文件中 beans 的 autowire 属性设置为 constructor。然后&#xff0c;它尝试把它的构造函数的参数…

ssm(Spring+Spring mvc+mybatis)Spring配置文件——applicationContext-servlet.xml

<?xml version"1.0" encoding"UTF-8"?> <beansxmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:p"http://www.springframework.org/schema/p"xm…

【南京】.Net 开源基础服务线下技术交流会

南京地区的.net开发人员对基础服务这块感兴趣的&#xff0c;欢迎大家参加及会后继续交流&#xff0c;踊跃参与&#xff01;若对基础服务相关有深度技术交流的&#xff0c;后续交换联系方式&#xff0c;可一起深度合作。 .NET技术行业落地分享交流会 邀请南京地区.NET技术专家和…

mysql 语句块语法_MySQL ------ MySQL常用语句的语法 (三十四)

MySQL常用的语句语法注意&#xff1a;1、 | 符号用来指出几个选中中的一个&#xff0c;因此NULL | NOT NULL 表示给出null 或 not null2、包含在方括号中的关键字或子句是可选的(如 [like this])3、既没有列出所有的MySQL语句&#xff0c;也没有列出每一条子句和选项4、大写的表…

ssm(Spring+Spring mvc+mybatis)Spring配置文件——applicationContext.xml

<?xml version"1.0" encoding"UTF-8"?> <beansxmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns:p"http://www.springframework.org/schema/p"xm…

图的广度优先算法+遍历

图解 代码实现 package com.atguigu.graph;import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList;/*** 创建人 wdl* 创建时间 2021/4/2* 描述*/ public class Graph {private ArrayList<String> vertexList;//存储顶点集合private int[][…

Spring @Required 注释

转载自 Spring Required 注释 Spring Required 注释 Required 注释应用于 bean 属性的 setter 方法&#xff0c;它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中&#xff0c;否则容器就会抛出一个 BeanInitializationException 异常。下面显示的是一个使用 Requir…

vue父子组件生命周期顺序_vue父子组件生命周期执行顺序

Parent-- Child1-- Child2装载parent beforeCreateparent createdparent beforeMountchild1 beforeCreatechild1 createdchidl1 beforeMountchild2 brforeCreatechild2 createdchild2 beforeMountchild1 mountedchild2 mountedparent mounted更新parent beforeUpdatechild1 bef…

.Net异步编程知多少

1. 引言 最近在学习Abp框架&#xff0c;发现Abp框架的很多Api都提供了同步异步两种写法。异步编程说起来&#xff0c;大家可能都会说异步编程性能好。但好在哪里&#xff0c;引入了什么问题&#xff0c;以及如何使用&#xff0c;想必也未必能答的上来。 自己对异步编程也不是很…

指纹识别开发1.0

在不久之前&#xff0c;用java和C#分别开发了个人脸识别&#xff0c;感觉挺不错的&#xff0c;于是脑袋一发热&#xff0c;想了想能不能搞个指纹识别&#xff0c;答案当然是能&#xff0c;那么问题来了&#xff0c;在人脸识别的时候可以借助自带摄像头提取你的face&#xff0c;…

Spring @Autowired 注释

转载自 Spring Autowired 注释 Spring Autowired 注释 Autowired 注释对在哪里和如何完成自动连接提供了更多的细微的控制。 Autowired 注释可以在 setter 方法中被用于自动连接 bean&#xff0c;就像 Autowired 注释&#xff0c;容器&#xff0c;一个属性或者任意命名的可…

DFS VS BFS

实际案例 代码实现 package com.atguigu.graph;import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList;/*** 创建人 wdl* 创建时间 2021/4/2* 描述*/ public class Graph {private ArrayList<String> vertexList;//存储顶点集合private in…

CLR运行时细节 - Method Descriptor

方法描述符:MethodDesc 运行时用来描述类型的托管方法,它保存在方法描述桶(MethodDescChunk)内;方法描述符保存了方法在运行时的一些重要信息:是否JIT编译;是否有方法表槽(决定了方法入口是跟在方法描述符(MethodDesc)后还是在方法表(MethodTable)后面);距离MethodDescChunk的索…

beanutil 批量copy_BeanUtils.copyProperties 需要getset方法支持

今天在调用这个方法时&#xff0c;发现属性没有映射上&#xff0c;结果一看是model类没有加上getset方法 PropertyDescriptor[] targetPds getPropertyDescriptors(actualEditable); List ignoreList (ignoreProperties ! null ? Arrays.asList(ignoreProperties) : null);f…

ssm(Spring+Spring mvc+mybatis)mybatis配置文件——mybatis-config.xml

<?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><settings><!-- 打印查…

2015蓝桥杯省赛---java---B---3(三羊献瑞)

题目 三羊献瑞 思路分析 由于是填空题&#xff0c;没有时间和内存的要求&#xff0c;所以看到这个题&#xff0c;第一想法就是暴力破解&#xff0c;当然了&#xff0c;怎么快就怎么做。 由于 "三"是数字的首位&#xff0c;低位的数字进位后必然为1&#xff0c;所…

Spring @Qualifier 注释

转载自 Spring Qualifier 注释 Spring Qualifier 注释 可能会有这样一种情况&#xff0c;当你创建多个具有相同类型的 bean 时&#xff0c;并且想要用一个属性只为它们其中的一个进行装配&#xff0c;在这种情况下&#xff0c;你可以使用 Qualifier 注释和 Autowired 注释通…

mysql common是什么_MySQL common_schema简介

common_schema为MySQL提供了查询脚本&#xff0c;分析并且信息化的视图和一个函数库&#xff0c;以便更容易的管理和诊断。它引入的一些基于SQL的工具简common_schema的简介&#xff1a;Shlomi Noach 的common_schema项目()是一套针对服务器脚本化和管理的强大的代码和视图。co…