async&await=custom IAsyncStateMachine
async&await是IAsyncStateMachine的语法糖
验证
分别使用async&await和IAsyncStateMachine遍历一棵树,查看二者的线程id和线程上下文标识是否相同
数据结构
public class Node
{
private static List<Node> _nodes = new List<Node>();
private static int _id = 1;
public Node()
{
this.Id = _id++;
_nodes.Add(this);
}
public int Id { get; }
public Node Left { get; set; }
public Node Right { get; set; }
public bool IsLeaf => this.Left == null && this.Right == null;
public bool IsTraveled { get; set; } = false;
public override string ToString()
{
return $"{Left?.Id ?? 0}|{this.Id}|{Right?.Id ?? 0}";
}
}
使用async&await遍历树
public static async Task<int> Travle(Node node)
{
node.IsTraveled = true;
if (!node.IsLeaf)
{
Console.WriteLine("线程id:" + Thread.CurrentThread.ManagedThreadId + "|线程上下文标识:" + Thread.CurrentThread.ExecutionContext.GetHashCode() + ":" + await Travle(node.Left));
Console.WriteLine("线程id:" + Thread.CurrentThread.ManagedThreadId + "|线程上下文标识:" + Thread.CurrentThread.ExecutionContext.GetHashCode() + ":" + await Travle(node.Right));
}
return node.Id;
}
使用IAsyncStateMachine遍历树
public static Task<int> StateMechineTravle(Node node)
{
StateMechine stateMechine = new StateMechine();
stateMechine.node = node;
stateMechine.builder = AsyncTaskMethodBuilder<int>.Create();
stateMechine.state = -1;
AsyncTaskMethodBuilder<int> next_builder = stateMechine.builder;
next_builder.Start<StateMechine>(ref stateMechine);
return stateMechine.builder.Task;
}
这里StateMechine是实现IAsyncStateMachine接口的一个类
public struct StateMechine : IAsyncStateMachine
{
public int state;
public AsyncTaskMethodBuilder<int> builder;
public Node node;
private object wrap1;
private object wrap2;
private TaskAwaiter<int> awaiter;
void IAsyncStateMachine.MoveNext()
{
int num = this.state;
int id;
try
{
TaskAwaiter<int> taskAwaiter;
if (num != 0)
{
if (num == 1)
{
taskAwaiter = this.awaiter;
this.awaiter = default(TaskAwaiter<int>);
this.state = -1;
goto IL_1AB;
}
this.node.IsTraveled = true;
if (this.node.IsLeaf)
{
goto IL_20C;
}
this.wrap1 = Thread.CurrentThread.ManagedThreadId;
this.wrap2 = Thread.CurrentThread.ExecutionContext.GetHashCode();
taskAwaiter = Program.StateMechineTravle(this.node.Left).GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.state = 0;
this.awaiter = taskAwaiter;
this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, StateMechine>(ref taskAwaiter, ref this);
return;
}
}
else
{
taskAwaiter = this.awaiter;
this.awaiter = default(TaskAwaiter<int>);
this.state = -1;
}
int arg_CC_0 = taskAwaiter.GetResult();
taskAwaiter = default(TaskAwaiter<int>);
object obj = arg_CC_0;
Console.WriteLine(string.Concat(new object[]
{
"线程id:",
this.wrap1,
"|线程上下文标识:",
this.wrap2,
":",
obj
}));
this.wrap1 = null;
this.wrap2 = null;
this.wrap2 = Thread.CurrentThread.ManagedThreadId;
this.wrap1 = Thread.CurrentThread.ExecutionContext.GetHashCode();
taskAwaiter = Program.StateMechineTravle(this.node.Right).GetAwaiter();
if (!taskAwaiter.IsCompleted)
{
this.state = 1;
this.awaiter = taskAwaiter;
this.builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, StateMechine>(ref taskAwaiter, ref this);
return;
}
IL_1AB:
int arg_1BA_0 = taskAwaiter.GetResult();
taskAwaiter = default(TaskAwaiter<int>);
obj = arg_1BA_0;
Console.WriteLine(string.Concat(new object[]
{
"线程id:",
this.wrap2,
"|线程上下文标识:",
this.wrap1,
":",
obj
}));
this.wrap2 = null;
this.wrap1 = null;
IL_20C:
id = this.node.Id;
}
catch (Exception exception)
{
this.state = -2;
this.builder.SetException(exception);
return;
}
this.state = -2;
this.builder.SetResult(id);
}
[DebuggerHidden]
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
this.builder.SetStateMachine(stateMachine);
}
}
结果
输入1,使用async&await遍历树
输入2,使用IAsyncStateMachine遍历树
可以看出,二者一毛一样
可见,基于async和await的task不会被多线程调用
示例代码
https://github.com/snys98/AsyncStateMechineTest