zoukankan      html  css  js  c++  java
  • async await随笔

    一些随笔

    理解一些名词(简单的说,具体定义可百度)

    并发(concurrency):同一时间段内执行多个任务,但是在同一时刻你只可以执行一个任务。

    并行(parallellism):同一时刻执行多个任务。

    同步异步关注的是消息通信机制

    同步(Synchronous):调用方必须等待这个调用返回结果才能继续执行。

    异步(Asynchronous):调用方不会立刻得到结果,而是调用发出后调用者可以继续后续的操作,而被调用者后续,当完成时会通知调用者完成后续操作。

    async await

    我们一般将async修饰的方法叫做 "异步方法" ,这并不一定意味着方法是异步执行的。这也不意味着该方法是异步的。它只意味着编译器对方法执行一些特殊的转换。

    示例1

    
    static async Task Main() 
    {
        await Task.Run(()=>Console.WriteLine("111"));
        Console.Write("22");
    }
    
    

    生成的C#代码

    1.委托,编译器会给我们生成一个类和一个实例方法

    
    // ()=>Console.WriteLine("111")
    [Serializable]
    [CompilerGenerated]
    private sealed class <>c
    {
        public static readonly <>c <>9 = new <>c();
    
        public static Action <>9__0_0;
    
        internal void <Main>b__0_0()
        {
            Console.WriteLine("111");
        }
    }
    
    

    2.编译器为async 生成的代码

    
    [StructLayout(LayoutKind.Auto)]
    [CompilerGenerated]
    private struct <Main>d__0 : IAsyncStateMachine
    {
        public int <>1__state;
    
        public AsyncTaskMethodBuilder <>t__builder;
    
        private TaskAwaiter <>u__1;
    
        private void MoveNext()
        {
            int num = <>1__state;
            try
            {
                TaskAwaiter awaiter;
                if (num != 0)
                {
                    awaiter = Task.Run(<>c.<>9__0_0 ?? (<>c.<>9__0_0 = new Action(<>c.<>9.<Main>b__0_0))).GetAwaiter();
                    if (!awaiter.IsCompleted)
                    {
                        num = (<>1__state = 0);
                        <>u__1 = awaiter;
                        <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
                        return;
                    }
                }
                else
                {
                    awaiter = <>u__1;
                    <>u__1 = default(TaskAwaiter);
                    num = (<>1__state = -1);
                }
                awaiter.GetResult();
                Console.Write("22");
            }
            catch (Exception exception)
            {
                <>1__state = -2;
                <>t__builder.SetException(exception);
                return;
            }
            <>1__state = -2;
            <>t__builder.SetResult();
        }
    
        void IAsyncStateMachine.MoveNext()
        {
            //ILSpy generated this explicit interface implementation from .override directive in MoveNext
            this.MoveNext();
        }
    
        [DebuggerHidden]
        private void SetStateMachine(IAsyncStateMachine stateMachine)
        {
            <>t__builder.SetStateMachine(stateMachine);
        }
    
        void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
        {
            //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
            this.SetStateMachine(stateMachine);
        }
    }
    
    

    分析状态机每个字段

    • 编译器为 async修饰的方法 生成的了一个结构体 <Main>d__0,实现了IAsyncStateMachine接口,这个接口有2个方法:

    • void MoveNext() 执行下一步

    • void SetStateMachine(IAsyncStateMachine stateMachine) 设置状态

    为什么会各自实现2个 是因为ILSpy通过setstatemmachine中的.override指令生成了这个显式的接口实现,这个不用管.

    • public int <>1__state 状态值

    • public AsyncTaskMethodBuilder <>t__builder Provides a builder for asynchronous methods that return(为返回的异步方法提供构建器),它保存完成的任务(非常类似于TaskCompletionSource<T>类型),并管理状态机的状态转换。

    • private TaskAwaiter <>u__1 Provides an awaiter for awaiting a (提供一个等候者),它封装了一个任务,并在需要时安排任务的延续(类似于Task.ContinueWith(), 延续的是封装的是 await 后 未完成的),

    上述例子 如果Task.Run().GetAwaiter(); 状态不是完成,IsCompleted = false, 则会把后续 Task.Run(<>c.<>9__0_0),和cw("222") 作为一个延续。


    分析执行流程

    
    [AsyncStateMachine(typeof(<Main>d__0))] 
    private static Task Main(string[] args)
    {
        <Main>d__0 stateMachine = default(<Main>d__0);
        stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
        stateMachine.<>1__state = -1;
        stateMachine.<>t__builder.Start(ref stateMachine);
        return stateMachine.<>t__builder.Task;
    }
    
    
    • Main函数执行,关联要执行的状态机,并Create一个异步方法构建器, 初始化结构体<Main>d__0,初始化状态机状态为-1;

    • 执行关联的状态机 stateMachine.<>t__builder.Start(ref stateMachine) 参数为关联的状态机<Main>d__0

    • start发生了什么? 先只看核心的:在正确的执行上下文中使用 调用了 stateMachine.MoveNext();

    
    /// <summary>Initiates the builder's execution with the associated state machine.</summary>
    /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
    /// <param name="stateMachine">The state machine instance, passed by reference.</param>
    [DebuggerStepThrough]
    public static void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
    {
        if (stateMachine == null) // TStateMachines are generally non-nullable value types, so this check will be elided
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.stateMachine);
        }
    
        // enregistrer variables with 0 post-fix so they can be used in registers without EH forcing them to stack
        // Capture references to Thread Contexts
        Thread currentThread0 = Thread.CurrentThread;
        Thread currentThread = currentThread0;
        ExecutionContext? previousExecutionCtx0 = currentThread0._executionContext;
    
        // Store current ExecutionContext and SynchronizationContext as "previousXxx".
        // This allows us to restore them and undo any Context changes made in stateMachine.MoveNext
        // so that they won't "leak" out of the first await.
        ExecutionContext? previousExecutionCtx = previousExecutionCtx0;
        SynchronizationContext? previousSyncCtx = currentThread0._synchronizationContext;
    
        try
        {
            stateMachine.MoveNext();
        }
        finally
        {
            // Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack
            SynchronizationContext? previousSyncCtx1 = previousSyncCtx;
            Thread currentThread1 = currentThread;
            // The common case is that these have not changed, so avoid the cost of a write barrier if not needed.
            if (previousSyncCtx1 != currentThread1._synchronizationContext)
            {
                // Restore changed SynchronizationContext back to previous
                currentThread1._synchronizationContext = previousSyncCtx1;
            }
    
            ExecutionContext? previousExecutionCtx1 = previousExecutionCtx;
            ExecutionContext? currentExecutionCtx1 = currentThread1._executionContext;
            if (previousExecutionCtx1 != currentExecutionCtx1)
            {
                ExecutionContext.RestoreChangedContextToThread(currentThread1, previousExecutionCtx1, currentExecutionCtx1);
            }
        }
    }
    
    

    // TODO FOR HERE

    ExecutionContext(执行上下文)

    SynchronizationContext(同步上下文)

  • 相关阅读:
    0x00 Java 研习录
    0x00 Linux From Scratch 实战
    第一章:Java编程入门
    陈洋总结
    pthread_detach
    explicit用法
    Java动态加载DLL方法
    ToolHelp32 函数
    android根据子view里面的数量自动排版的一个ViewGroup
    安装CocoaPods学习
  • 原文地址:https://www.cnblogs.com/caiyangcc/p/14248053.html
Copyright © 2011-2022 走看看