C# 图解await

下图通过图解进一步解释await执行逻辑。

  首先要明确的一点是,await用于进入异步阻塞等待,如await A()即异步等待A方法执行完毕再向下执行。

  下图为await基本使用方法(本图通过树状图代替代码,便于直观理解,每个节点代表一行代码,代码由上向下顺序执行)。首先进入Main方法执行print 1打印1和主线程ID,然后主线程调用方法T(),继续执行print 3打印3和主线程ID,然后执行到await时,需要创建一个子线程,由子线程执行await后面的方法(此处是Task.Delay(1000)),并且同时通知主线程,继续向下执行该方法(此处即T()方法)之后的代码行,因此主线程会立刻打印2和主线程ID,而子线程执行完Delay延时函数后,会打印4和子线程ID。因此最终的输出结果是:1 3 2 4

在这里插入图片描述

  上图能够直观体现出await的用处,跳出当前阻塞让主线程继续向下执行,前提是await所在方法(即T()方法)不被其调用者(Main()方法)await,下面来看一下await T()的情况。

在这里插入图片描述

  首先有一点问题需要注意:如果一个方法内部使用await关键字,那么该方法必然是一个异步方法,那么需要在声明时使用async关键字标明这是个异步方法,但如果将C#控制台程序的Main方法标记为async会报错,原因是编译器不能解析异步的Main方法,因此找不到合适的入口点,因此在控制台的Main方法中不能使用await关键字,此处的Main()可以理解为一个普通的测试方法。

  await中文释义是“等待”,如果使用await T(),则Main方法内部的代码是顺序执行的,执行到T()时会等待T()内部全部执行完毕后再向下执行。因此整个输出顺序是1 3 4 2。但同样,Main方法变为异步,假如外部有一个方法调用Main方法,执行到Main方法,并当T()方法执行到await时,会创建一个子线程继续执行Main方法,主线程回到外部方法中继续执行。由此可见,await同步阻塞其后面所跟异步方法,但同样又会使其所在方法变为异步(第一张图同理)

关于await多层调用的图解:

在这里插入图片描述

  上图输出结果是:1 主(主线程ID,下同)、3 主、5 主、7 主、2 主、8 子1(子线程1 ID)、x1 子1、x2 子N、6 子N、4 子N,其中,G方法进入异步时是由子线程1执行,但await时的结果并不一致,有时后续x2是子线程1执行,有时系统又创建了一个新的子线程来执行后续代码,推断可能是由于有时执行到G方法的await时子线程1已被销毁所致,由此可见,同一方法内的多个await是同步顺序

在这里插入图片描述

  上图输出结果为:1 主、3 主、5 主、7 主、x1 主、2 主、8 子1、x2 子2、6 子2、4 子2,其中8与(2,6,4)之间本身是并行的,因此顺序可能会有颠倒,

在这里插入图片描述

  上图执行顺序为:1 主、3 主、5 主、x1 主、2 主、x2 子1、7 子1、6 子1、4 子1、8 子1或2(此处的代码有可能由子线程1执行,这取决于6处(Z方法之后的代码)耗时长短,如果await后子线程1尚未执行完毕会新开一个线程,否则会继续使用子线程1来执行print 8,只需要在print 6与Z()之间添加一行Thread.Sleep(3000)即可看出差异)

  上述图片其实都是源自两种情况:一种是await T(),另一种是T();前者进入异步等待,执行完毕后才会向下执行,后者执行到底层异步接口后会创建子线程继续执行await的方法,并返回到当前行由主线程继续向下执行

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值