ETTask
核心代码与C#原生参考
| ET | 原生 | 含义 |
|---|---|---|
| ETTask | Task | |
| AsyncETTaskMethodBuilder | AsyncTaskMethodBuilder | 返回任务的异步方法生成器 |
| ETTaskCompletionSource | TaskAwaiter | 返回给await的等待者 |
| MoveNextRunner | 用于捕获当前执行上下文 |
TASK LIKE需求:
-
async:自定义异步方法生成器
Create()方法
Start()方法
SetResult()方法
Task 自定义Task的Get属性
-
await
自定义Task类需要有GetAwaiter()方法
-
Task:自定义Task
标明特性
[System.Runtime.CompilerServices.AsyncMethodBuilder(typeof(自定义异步方法生成器))]GetAwaiter()方法返回一个自定义Awaiter
-
Awaiter:自定义Awaiter
需要实现
INotifyCompletion或ICriticalNotifyCompletion接口bool IsCompleted {get;}属性
GetResult()方法
OnCompleted()方法
ET自定义Task核心类讲解
关于作用于异步方法返回标识
[AsyncMethodBuilder(typeof(AsyncETTaskMethodBuilder))]
public partial struct ETTask : IEquatable<ETTask>{}
如果希望自定义的Task能够返回参数,需要为其标注[AsyncMethodBuilder(typeof(返回任务的异步方法生成器类))]标识,如果没有这个标识,async是不会让我们的自定义任务带参返回的,编译器会直接报错。
AsyncETTaskMethodBuilder返回任务的异步方法生成器

其中Creater、Task、Start、SetResult方法是刚需
ETTaskCompletionSourceETTask返回源,真正意义上的Awaiter

ETTask

核心方法为GetAwaiter,返回Awaiter对象
其他方法多为Awaiter与ETTaskCompletionSource方法的桥接
Awaiter ETTaskCompletionSource的代理类

await ETTask运行流程
在C#编译器中会识别三个异步关键字
方法外部await关键字,如果在调用方法前添加了该关键字,编译器会将等待的方法转换成状态机
方法上async关键字,如果标识了该关键字,编译器则会查找返回类型的特性是否包含AsyncMethodBuilder,如果返回对象没有该特性,且不是void返回,编辑器会报错
方法内部await关键字,方法内部没有await关键字,编译器会将该方法以同步的方式执行
当前面说的三个关键字都存在,且返回类型添加了AsyncMethodBuilder特性,接下来就可以分析异步的执行流程了,以ETTask为例
首先编译器会将等待的方法转换成状态机
调用
AsyncMethodBuilder.Type的Create方法,创建一个AsyncETTaskMethodBuilder-
接下来调用
AsyncETTaskMethodBuilder的Start方法运作状态机(如果没有方法内部没有
await关键字,方法将会以同步方式执行,直接跳到第9步然后再从第4步开始执行) 然后
await操作符会调用ETTask的GetAwaiter方法,创建一个Awaiter返回给状态机-
状态机调用
Awaiter的IsCompleted属性- 如果操作已经以同步方式完成了,属性将返回True
- 继续调用
Awaiter的GetResult方法,该方法要么抛出异常,要么返回结果
- 继续调用
- 如果操作以异步方式完成,属性将返回False
- 状态机机调用
Awaiter的OnCompleted方法,并向它传递一个委托(引用状态机的MoveNext方法)
- 状态机机调用
- 如果操作已经以同步方式完成了,属性将返回True
现在状态机允许它回到线程原地以执行其他代码。将来某个时候,封装了底层任务的
Awaiter会在完成时调用委托以执行MoveNext。当异步方法执行完毕后,会调用
AsyncETTaskMethodBuilder的SetResult方法,为Awaiter写入结果-
这时
Awaiter调用GetResult方法,该方法要么抛出异常,要么返回结果可根据状态机中的字段知道如何到达代码中的正确位置,使方法能从他当初离开的位置继续执行
public async static void Test()
{
await M_ETTask_1();
await M_ETTask_2();
}
static async ETTask M_ETTask_1()
{
return;
}
static ETTask M_ETTask_2()
{
return new ETTask();
}
如果方法加上async关键字,await会从AsyncETTaskMethodBuilder的Task属性中获取ETTask
如果没有async关键字,await会从方法返回获取ETTask;
ETVoid
ETVoid

可以看到相对于ETTask,ETVoid省略了大部分方法,且在调用Awaiter.IsCompleted属性是必然是返回Ture;
AsyncETVoidMethodBuilder

在AsyncETVoidMethodBuilder中与AsyncETTaskMethodBuilder的不同之处在于不再依靠Task,且SetResult与SetException方法都变成了空方法