• async&await的前世今生


    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遍历树
    可以看出,二者一毛一样
    1


    2

    可见,基于async和await的task不会被多线程调用

    示例代码

    https://github.com/snys98/AsyncStateMechineTest

    官方资料

    https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.compilerservices.iasyncstatemachine?view=netframework-4.7.1

    我们是Microex,致力于.net技术的探索。 如果你对我们感兴趣的话,请关注:https://github.com/microexs。 加群【Microex】:595638331 点我加群(免费)
  • 相关阅读:
    Jerry的反省:程序员不要轻易说出"这个功能技术上无法实现"
    深入学习SAP UI5框架代码系列之三:HTML原生事件 VS UI5 Semantic事件
    SAP UI5和Angularjs事件处理机制的实现比较
    如何通过调试找到自己需要的ABAP增强
    深入学习SAP UI5框架代码系列之二:UI5 控件的渲染器
    LiteOS内核源码分析:动态内存之Bestfit分配算法
    破解class文件的第一步:深入理解JAVA Class文件
    轻松带你学习java-agent
    https如何使用python+flask来实现
    三步法助你快速定位网站性能问题
  • 原文地址:https://www.cnblogs.com/Microex/p/8360457.html
Copyright © 2020-2023  润新知