学习来源:《CLR via C by Jeffrey Richter 》第四版,第28章 28.3编译器如何将异步函数转换成状态机
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace test2
{
internal class Program
{
static void Main(string[] args)
{
}
//原方法和书上的是一样的
internal class Type1 { }
internal class Type2 { }
#region 原方法
//public static async Task Method1Async()
//{
// return new Type1();
//}
//public static async Task Method2Async()
//{
// return new Type2();
//}
//public static async Task MymethodAsync(int argument)
//{
// int local = argument;
// try
// {
// Type1 result1 = await Method1Async();
// for (int i = 0; i < 3; i++)
// {
// Type2 result2 = await Method2Async();
// }
// }
// catch (Exception)
// {
// Console.WriteLine("catch");
// }
// finally
// {
// Console.WriteLine("finally");
// }
// return "Done";
// }
//反编译的和书上的不同
//状态机结构
#endregion
#region 编译器编译后
[CompilerGenerated]
private sealed class StateMachine1 : IAsyncStateMachine
{
public int state;
public AsyncTaskMethodBuilder builder;
private void MoveNext()
{
int num = state;
Type1 result;
try
{
result = new Type1();
}
catch (Exception exception)
{
state = -2;
builder.SetException(exception);
return;
}
state = -2;
builder.SetResult(result);
}
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);
}
}
//结构也可以,类型也可以
[CompilerGenerated]
private sealed class StateMachine2 : IAsyncStateMachine
{
public int state;
public AsyncTaskMethodBuilder builder;
private void MoveNext()
{
int num = state;
Type2 result;
try
{
result = new Type2();
}
catch (Exception exception)
{
state = -2;
builder.SetException(exception);
return;
}
state = -2;
builder.SetResult(result);
}
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);
}
}
//结构也可以,类型也可以
//状态机结构
[CompilerGenerated]
private struct StateMachine3 : IAsyncStateMachine
{
//代表状态机builder (task)及其位置字段
public AsyncTaskMethodBuilder builder;
public int state;
//实参和局部变量成了字段。
public int argument;
private int local;
private Type1 result1;
private Type2 result2;
private int i;
//每个awaiter修饰的函数都成了一个字段,包含返回值
//任何时候这些字段只有一个是重要的,那个字段引用最近执行的,以异步方式完成await
private TaskAwaiter m_awaiter;
private TaskAwaiter m_awaiter2;
//状态机方法本身
//调用多少次await,就调用多少次这个方法,每次都调用await修饰的方法,每次都是根据状态判断调用的方法。
private void MoveNext()
{
//task结果
string result;
//编译器插入try来确保状态机任务完成
try
{
if (state > 1)//如果第一次进入MoveNext方法就执行。不管是哪个await触发都会执行
{
local = argument;//主线程执行的内容
}
try
{
TaskAwaiter l_awaiter2;
TaskAwaiter l_awaiter;
if (state != 0)
{
if (state == 1)//说明要执行循环是第二次执行MoveNext
{
l_awaiter2 = m_awaiter2;
m_awaiter2 = default(TaskAwaiter);
state = -1;//重新设置状态,以便后面异步选择
goto ForLoopEpilog;
}
//state>1的时候
//调用Method1Async获得l_awaiter的Awaiter Type1 result1 = await Method1Async();
l_awaiter = Method1Async().GetAwaiter();
if (!l_awaiter.IsCompleted)
{
state = 0;//重新设置状态,以便后面异步选择
m_awaiter = l_awaiter;//保存Awaiter以便后面返回
//让l_awaiter操作完成时调用MoveNext
//l_awaiter的OnCompleted,它会在被等待的任务上调用ContinueWith(t=>MoveNext()),任务完成后ontinueWith任务调用MoveNext
builder.AwaitUnsafeOnCompleted(ref l_awaiter, ref this);//this.MoveNext();
//线程返回给调用者(第一个同步完成)Type1 result1 = await Method1Async();
return;
}
}
else// state = 0;的时候
{
l_awaiter = m_awaiter;
m_awaiter = default(TaskAwaiter);
state = -1;//重新设置状态,以便后面异步选择
}
result1 = l_awaiter.GetResult();//获取 Type1 result1 = await Method1Async();的结果
i = 0;
ForLoopBody:
if (i < 3)//for循环判断
{
//获取l_awaiter2的Awaiter
l_awaiter2 = Method2Async().GetAwaiter();
//判断是否完成
if (!l_awaiter2.IsCompleted)
{
//重新设置状态,以便后面异步选择
state = 1;
//保存l_awaiter2以便返回
m_awaiter2 = l_awaiter2;
//让l_awaiter2操作完成是调用MoveNext()
builder.AwaitUnsafeOnCompleted(ref l_awaiter2, ref this);//this.MoveNext();
//线程返回给调用者
return;
}
//直到不满足条件继续循环
goto ForLoopEpilog;
}
result1 = null;
goto end_IL_001d;
ForLoopEpilog:
result2 = l_awaiter2.GetResult();//获取结果上一次执行 Type2 result2 = await Method2Async();的结果
i++;//每次循环都自增
goto ForLoopBody;//跳到循环体
end_IL_001d:;
}
catch (Exception)
{
Console.WriteLine("catch");
}
finally
{
if (state < 0)
{
Console.WriteLine("finally");
}
}
result = "Done";
}
catch (Exception exception)
{
state = -2;
builder.SetException(exception);
return;
}
state = -2;
builder.SetResult(result);
}
//理解后,我重写了下
//调用多少次await,就调用多少次这个方法,每次都调用await修饰的方法,每次都是根据状态判断调用的方法。
private void MyMoveNext() {
string result = string.Empty;
TaskAwaiter l_awaiter2;
TaskAwaiter l_awaiter;
if (state > 1)//如果第一次进入MoveNext方法就执行。不管是哪个await触发都会执行
{
local = argument;//主线程执行的内容
//state>1的时候
//调用Method1Async获得l_awaiter的Awaiter Type1 result1 = await Method1Async();
l_awaiter = Method1Async().GetAwaiter();
if (!l_awaiter.IsCompleted)
{
state = 0;//重新设置状态,以便后面异步选择 用于第二次进入此方法
m_awaiter = l_awaiter;//保存Awaiter以便后面返回
//让l_awaiter操作完成时调用MoveNext
//l_awaiter的OnCompleted,它会在被等待的任务上调用ContinueWith(t=>MoveNext()),任务完成后ontinueWith任务调用MoveNext
builder.AwaitUnsafeOnCompleted(ref l_awaiter, ref this);//this.MoveNext();,这样就可以调用当前数据的此方法,数据不变
//线程返回给调用者(第一个同步完成)Type1 result1 = await Method1Async();
return;
}
}
else {
// state = 0;的时候也就是i=0的时候
if (state == 0)
{
l_awaiter = m_awaiter;
m_awaiter = default(TaskAwaiter);
state = -1;//重新设置状态,以便后面异步选择
result1 = l_awaiter.GetResult();//获取 Type1 result1 = await Method1Async();的结果
i = 0;
}
else {
// state = 1;的时候也就是i>0的时候
l_awaiter2 = m_awaiter2;
m_awaiter2 = default(TaskAwaiter);
result2 = l_awaiter2.GetResult();//获取结果上一次执行 Type2 result2 = await Method2Async();的结果
i++;//每次循环都自增
}
while (i < 3) //for循环判断
{
//获取l_awaiter2的Awaiter
l_awaiter2 = Method2Async().GetAwaiter();
//判断是否完成
if (!l_awaiter2.IsCompleted)
{
//重新设置状态,以便后面异步选择
state = 1; //也是i > 0的时候
//保存l_awaiter2以便返回
m_awaiter2 = l_awaiter2;
//让l_awaiter2操作完成是调用MoveNext()
builder.AwaitUnsafeOnCompleted(ref l_awaiter2, ref this);//this.MoveNext();
//线程返回给调用者
return;
}
result2 = l_awaiter2.GetResult();//获取结果上一次执行 Type2 result2 = await Method2Async();的结果
i++;//每次循环都自增
}
//循环await结束
state = -1;//重新设置状态,以便后面异步选择
}
}
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);
}
}
//AsyncStateMachine指出这是个异步方法(对使用反射工具有用)
//StateMachine1类型指出实现状态机的结构类型
[AsyncStateMachine(typeof(StateMachine1))]
[DebuggerStepThrough]
public static Task Method1Async()
{
//创建状态机并初始化
StateMachine1 stateMachine = new StateMachine1();
//创建builder,从这个存跟方法返回Type1对象
//状态机使用builder来设置完成/异常
stateMachine.builder = AsyncTaskMethodBuilder.Create();
//初始化状态
stateMachine.state = -1;
//开始执行状态机
stateMachine.builder.Start(ref stateMachine);
//返回状态机task;
return stateMachine.builder.Task;
}
[AsyncStateMachine(typeof(StateMachine2))]
[DebuggerStepThrough]
public static Task Method2Async()
{
StateMachine2 stateMachine = new StateMachine2();
stateMachine.builder = AsyncTaskMethodBuilder.Create();
stateMachine.state = -1;
stateMachine.builder.Start(ref stateMachine);
return stateMachine.builder.Task;
}
//AsyncStateMachine指出这是个异步方法(对使用反射工具有用)
//StateMachine1类型指出实现状态机的结构类型
[AsyncStateMachine(typeof(StateMachine3))]
[DebuggerStepThrough]
public static Task MymethodAsync(int argument)
{
//创建状态机并初始化
StateMachine3 stateMachine = new StateMachine3();
//创建builder,从这个存跟方法返回Type1对象
//状态机使用builder来设置完成/异常
stateMachine.builder = AsyncTaskMethodBuilder.Create();
//将实参拷贝到状态机字段
stateMachine.argument = argument;
//初始化状态
stateMachine.state = -1;
//开始执行状态机
stateMachine.builder.Start(ref stateMachine);
//返回状态机task;
return stateMachine.builder.Task;
}
#endregion
}
}