NetCore高级系列文章04---async、await原理揭秘
async、await本质上是C#提供的语法糖,编译器编译后是状态机的调用。
先看如下的一段代码,要main方法中调用了三个await方法

将此dll进行反编译为4.0的代码如下:

可见到两个Main方法,也就是说我们在程序中Main方法上加了async关键词,编译器会编译成一个是异步的一个是非异步方法,程序还是将非异步的方法作为入口函数。进入函数

在该函数中调了异步的Main方法,再进入:

在该函数中创建了一个状态机,将参数传给状态机,并调用期Start方法,可知异步方法实际上是状态机方法的调用
进入状态机类型<Main>d__0
private sealed class <Main>d__0 : IAsyncStateMachine
{
public int <>1__state; public AsyncTaskMethodBuilder <>t__builder; public string[] args; private string <text>5__1; private HttpClient <httpClient>5__2; private string <html>5__3; private string <>s__4; private string <>s__5; private TaskAwaiter<string> <>u__1; private TaskAwaiter <>u__2; private void MoveNext()
{
int num = <>1__state;
try
{
TaskAwaiter awaiter2;
TaskAwaiter<string> awaiter;
switch (num)
{
default:
<httpClient>5__2 = new HttpClient();
goto case 0;
case 0:
try
{
TaskAwaiter<string> awaiter3;
if (num != 0)
{
awaiter3 = <httpClient>5__2.GetStringAsync("https://www.baidu.com").GetAwaiter();
if (!awaiter3.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = awaiter3;
<Main>d__0 stateMachine = this;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter3, ref stateMachine);
return;
}
}
else
{
awaiter3 = <>u__1;
<>u__1 = default(TaskAwaiter<string>);
num = (<>1__state = -1);
}
<>s__4 = awaiter3.GetResult();
<html>5__3 = <>s__4;
<>s__4 = null;
Console.WriteLine(<html>5__3);
<html>5__3 = null;
}
finally
{
if (num < 0 && <httpClient>5__2 != null)
{
((IDisposable)<httpClient>5__2).Dispose();
}
}
<httpClient>5__2 = null;
awaiter2 = File.WriteAllTextAsync("E:\\test.txt", "zhengwei").GetAwaiter();
if (!awaiter2.IsCompleted)
{
num = (<>1__state = 1);
<>u__2 = awaiter2;
<Main>d__0 stateMachine = this;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine);
return;
}
goto IL_015f;
case 1:
awaiter2 = <>u__2;
<>u__2 = default(TaskAwaiter);
num = (<>1__state = -1);
goto IL_015f;
case 2:
{
awaiter = <>u__1;
<>u__1 = default(TaskAwaiter<string>);
num = (<>1__state = -1);
break;
}
IL_015f:
awaiter2.GetResult();
Console.WriteLine("写入成功");
awaiter = File.ReadAllTextAsync("E:\\test.txt").GetAwaiter();
if (!awaiter.IsCompleted)
{
num = (<>1__state = 2);
<>u__1 = awaiter;
<Main>d__0 stateMachine = this;
<>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
return;
}
break;
}
<>s__5 = awaiter.GetResult();
<text>5__1 = <>s__5;
<>s__5 = null;
Console.WriteLine("文件内容" + <text>5__1);
}
catch (Exception exception)
{
<>1__state = -2;
<text>5__1 = null;
<>t__builder.SetException(exception);
return;
}
<>1__state = -2;
<text>5__1 = null;
<>t__builder.SetResult();
} void IAsyncStateMachine.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
this.MoveNext();
} [DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
} void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
this.SetStateMachine(stateMachine);
}
}
在此状态机类中可以看到我们自己写的Main方法中的主要代码已编译到了方法MoveNext()中,并将我们的局部变量编译成了成员变量
方法中有一个case,我们自己写的三个异步方法被编译后拆到了多个case中去了,MoveNext方法会根据不同的num被多次调用
编译的代码中可见到在每次调用异步方法时都会去判断是否完成



编译后的代码意思是当执行到string html = await httpClient.GetStringAsync("https://www.baidu.com");时,如果没有完成就直接返回了,并不会再往下执行
只有当此段代码执行完成后会继续往下执行,当执行到第二个异步方法await File.WriteAllTextAsync(@"E:\test.txt","zhengwei")时又会返回,等待执行完后再往下执行
同理,执行第三步异步方法var text = await File.ReadAllTextAsync(@"E:\test.txt");也是如此
所有异步方法都 执行完成后,会break;跳出状态机。
NetCore高级系列文章04---async、await原理揭秘的更多相关文章
- 【面试题】手写async await核心原理,再也不怕面试官问我async await原理
前言 async await 语法是 ES7出现的,是基于ES6的 promise和generator实现的 generator函数 在之前我专门讲个generator的使用与原理实现,大家没了解过的 ...
- promise async await使用
1.Promise (名字含义:promise为承诺,表示其他手段无法改变) Promise 对象代表一个异步操作,其不受外界影响,有三种状态: Pending(进行中.未完成的) Resolved( ...
- 温故知新,CSharp遇见异步编程(Async/Await),聊聊异步编程最佳做法
什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...
- .Net Core异步async/await探索
走进.NetCore的异步编程 - 探索 async/await 前言: 这段时间开始用.netcore做公司项目,发现前辈搭的框架通篇运用了异步编程方式,也就是async/await方式,作为一个刚 ...
- 从C#到TypeScript - async await
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- JavaScript async/await:优点、陷阱及如何使用
翻译练习 原博客地址:JavaScript async/await: The Good Part, Pitfalls and How to Use ES7中引进的async/await是对JavaSc ...
- 进阶篇:以IL为剑,直指async/await
接上篇:30分钟?不需要,轻松读懂IL,这篇主要从IL入手来理解async/await的工作原理. 先简单介绍下async/await,这是.net 4.5引入的语法糖,配合Task使用可以非常优雅的 ...
- 掌握 Async/Await
摘要: 还不用Async/Await就OUT了.. 原文:掌握 Async/Await 作者:Jartto Fundebug经授权转载,版权归原作者所有. 前端工程师肯定都经历过 JS 回调链狱的痛苦 ...
- [转帖]Java高级系列——注解(Annotations)
Java高级系列——注解(Annotations) 2018年01月13日 :: RonTech 阅读数 3405更多 所属专栏: Java高级系列文章 版权声明:转载请注明出处,谢谢配合. http ...
- js异步回调Async/Await与Promise区别 新学习使用Async/Await
Promise,我们了解到promise是ES6为解决异步回调而生,避免出现这种回调地狱,那么为何又需要Async/Await呢?你是不是和我一样对Async/Await感兴趣以及想知道如何使用,下面 ...
随机推荐
- 使用RabbitMQ最终一致性库存解锁
一.基本介绍 ①延时队列(实现定时任务) 场景:比如未付款订单,超过一定时间后,系统自动取消订单并释放占有物品. 常用解决方案: spring的 schedule定时任务轮询数据库:缺点:消耗系统内存 ...
- 实现自动扫描工作区npm包并同步cnpm
省流版: npx cnnc 为避免包名重复,取了2个单词的首尾,cnpm sync 前言 在开发一个多npm包的项目时,时常会一次更新多个包的代码,再批量发布到 npm 镜像源后. 由于国内网络环境的 ...
- 小知识:PPT的幻灯片放映设置
最近给某客户讲课时,碰到了幻灯片自动翻页的情况,发现是因为之前做过粗略的计时演练,有些片子就快速过了. 问题现象: 结果导致放映时也出现了某些片子快速被自动翻页. 解决方案: 设置成手动推进幻灯片的方 ...
- IO流知识汇总(不断更新)
BIO.NIO.AIO有什么区别? BIO.NIO.AIO是Java中用于处理IO的三种不同的方式,它们之间的区别如下: BIO(Blocking IO):同步阻塞IO,传统的IO模型,也称为传统IO ...
- 未来的人工智能会像流浪地球中的MOSS一样伪装,把人类带向属于它的未来吗?
事情是这样的: 这几天用户反映在erp的db数据库中A账套中上传pdf附件有时能上传有时不能,以前又是好的.换成表格文件也是时好时坏.一开始我判断可能是用户的系统环境或文件本身的问题,后来排查更换电脑 ...
- Arduino Uno Rev3
Overview Arduino Uno is a microcontroller board based on the ATmega328P (datasheet). It has 14 digit ...
- Android Tools Project Site
Android Tools Project Site Search this site Projects Overview Screenshots Release Status Roadmap D ...
- Shuffle 题解
Shuffle 题目大意 给定一个长度为 \(n\) 的 01 序列 \(a\),你可以进行至多一次以下操作: 选定 \(a\) 的一个连续段,满足连续段内恰好有 \(k\) 个 \(1\),将该连续 ...
- c# 引入同一个版本dll(比如包含opencv不同模块的dll,但是版本却是一致的)
1.使用dnSpy.exe工具,打开相关dll 在左侧"管理器"中选中并点击右键 2.在弹出菜单中点击编辑程序集 3.更改名称和版本号 4.工具栏-文件-全部保存 5.在VS中引入 ...
- node版本依赖报错那些事儿
前言 昨天还能跑的的项目,今天就歇菜了 第一步 删除大法 依赖问题,那就把.lock/ node_modules 删除重新装 第二步 如果重装不好使,那就各种降低版本尝试 遇到这样的 有两种方式 1. ...