首页 > 其他分享 >NetCore高级系列文章04---async、await原理揭秘

NetCore高级系列文章04---async、await原理揭秘

时间:2023-12-28 15:14:34浏览次数:24  
标签:__ 异步 stateMachine 04 NetCore await private state num

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;跳出状态机。

 

标签:__,异步,stateMachine,04,NetCore,await,private,state,num
From: https://www.cnblogs.com/zhengwei-cq/p/17932744.html

相关文章

  • 1997-2004 英语二考研词汇
    1997年重点词汇阅读理解部分:1.parliamentaryadj.议会的2.territoryn.领土,版图,地域3incurablyadv.治不好地,不能矫正地4convincingadj.令人信服的,有力的,令人心悦诚服的5flashedvi.闪光,闪现,反射,使迅速6pickupv.掘地,捡起,获得,......
  • day01 代码随想录算法训练营 704. 二分查找
    题目:leetcode704.二分查找 感悟:困扰我多年的二分查找对于边界的判断,我终于理解了。难点:难点1:定边界rightright=len(nums)还是len(nums)-1 难点2:while循环whileleft<right还是left<=right 难点3:mid取值mid=right-1还是mid=right  结论:1.自己确定......
  • 03 CP2104串口驱动安装
    1概述串口是最常用的一种调试工具,开发过程中我们经常会使用串口输出一些调试信息,在LINUX下也会用串口控制台控制LINUX系统。目前的串口,大部分都是USB转串口。CP2104是一款非常稳定好用的USB转串口芯片。接下来我们看下如何进行驱动安装。2软件下载登录米联客技术论坛https://......
  • Unreal入门,开关04,蓝图通讯的几种方式(总结)
    1.直接调用,一开始做的开关就是这种方式,在地图编辑的时候给开关对象设置好关联的灯的引用,触发的时候直接调用灯提供的开关函数即可1.1给ActorSwitch添加一个ObjectReference成员1.2在地图编辑器中初始化这个成员,关联到ActorLight1.3在Overlap事件中通过ActorLight的引......
  • 初中英语优秀范文100篇-040My View on the Internet-网络之我见
    初中英语优秀范文100篇-040MyViewontheInternet-网络之我见PDF格式公众号回复关键字:SHCZFW040记忆树1NowmanyofmyclassmatesliketosurftheInternetintheirfreetime.翻译现在很多同学喜欢在空闲时间上网简化记忆上网句子结构1manyofmyclassmate......
  • 04变换约束
    CopyLocationConstraint复制位置约束复制位置约束强制约束对象和目标位置相同。CopyRotationConstraint复制旋转约束复制旋转约束强制约束对象匹配目标旋转。CopyScaleConstraint复制缩放约束复制缩放(CopyRotation)约束强制约束对象获得目标的缩放。复制变换约束复制......
  • 04020404网格工具
    工具栏网格编辑模式工具:选择   选择或移动。   框选       通过拖拉方框选择几何元素。   刷选       通过拖拉圆形选择几何元素。   套索选择       通过拖拉曲线选择几何元素。Cursor游标   更改3D游标的位置。移动   变换工......
  • 04修改器生成
       01,阵列修改器适配类型   控制决定阵列长度的方式。有三种选择,分别显示,曲线,长度,数量,这些设置这下面有解释:   适配曲线       在适配的曲线路径指定的长度范围内生成指定数量的副本。   适配长度       生成足够的副本,以符合长度给定......
  • 0402网格
       1,简介用于建模的模式有:物体模式   支持基础的操作比如创建对象、合并对象、管理形态键、管理UV层和顶点颜色层。编辑模式   主要用于网格编辑操作。雕刻模式   除了能够处理单独的网格元素,还支持通过笔刷进行雕刻(本章节不会涉及该内容)。   2,结构对于......
  • 0403曲线
    04,基本体参考模式   物体模式和编辑模式菜单   添加‣曲线快捷键   Shift-A贝塞尔曲线添加一段由2个控制点构成的开放2D贝塞尔曲线。贝塞尔圆环添加一个闭合的2D贝塞尔圆环(由四个控制点构成)。NURBS曲线添加一段由4个控制点构成的开放2DNURBS曲线,其结点均匀分......