C# 分析async和await修饰符

   学习来源:《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
    }
}

你可能感兴趣的:(c#)