Async/awit详解(一)

发布时间 2023-06-08 02:52:34作者: John的救赎

await/async

概念

     await/async C#保留关键字,通常是成对出现

async修饰方法,可以单独出现,但是有警告

await在方法体,只能出现在task/async方法前面,只有await会报错

 

一个async方法,如果没有返回值,可以方法声明返回Task

await/async能够用同步的方式编写代码,但又是非阻塞的

.NetFramework4.5----await/async 语法糖:由编译器提供的功能

 

语法

1只有async

   方法体只加async会有一个warn,和普通方法没有任何区别

        /// <summary>

        /// 只有async没有await

        /// 跟普通方法没有区别

        /// </summary>

        private static async void NoReturnNoAwait()

        {

            //主线程执行

            Task task = Task.Run(() =>//启动新线程完成任务

            {

                Thread.Sleep(1000);

                Console.WriteLine($"NoReturnNoAwait Sleep3000 before,ThreadId={Thread.CurrentThread.ManagedThreadId}");

                Thread.Sleep(1000);

                Console.WriteLine($"NoReturnNoAwait Sleep3000 after,ThreadId={Thread.CurrentThread.ManagedThreadId}");

            });

 

            //主线程执行

            Console.WriteLine($"NoReturnNoAwait Sleep after Task,ThreadId={Thread.CurrentThread.ManagedThreadId}");

        }

 

2只加await

   方法体会报错,因为await必须和async一起使用。

 

  1. asyncawait一起使用

    注意:await只能放在Task前面

await后面的代码会等着task任务的完成后再继续执行

其实就像把await后面的代码包装成一个continuwith的回调动作

然后这个回调动作可能新的子线程,也可能是主线程

以下代码执行过程:主线程开始执行打印------开启一个task线程执行任务----线程还在执行任务,主线程不等待继续往下执行

碰到await  task等待task里的任务执行完成然后往下执行最后一句打印,这个可能是主线程执行的,也可能是子线程执行的还可能是一

个新的线程执行的

 

  1. awit Task.run()

此时执行过程则是,主线程返回先做完自己的任务,然后再去开启线程执行任务(不阻塞),执行SumFactory111的打印

继续往下执行,又碰到了await 再次返回,完成第一个Task里的任务之后再去创建线程执行

注意:awit Task.run()等待之后,会把Task的任务执行完成,再往下执行,平常时Task里的任务还未执行完成就会往下执行

 

 

 

       

 

 

 

Async/await的好处

1 主线程(或子线程)遇见await就返回,非阻塞,去做自己的事,await后面新的线程也开始处理自己的任务

这两者之间是并发执行的

2 做到控制线程的顺序,其实就是以写同步方法的方式来异步编程

   

 

状态机

  1. 什么是状态机?

--类似于红绿灯: 红灯:停  绿灯:行;

一个对象在不同的状态可以执行的不同的行为

 

  1. 状态机原理解析

在一个普通方法上添加Async,在底层会生成一个状态机,状态模式

 

              1.实例化状态机

        2.把状态机实例交给一个build去执行

        3.整理线程的上下文

        4.stateMachine.MoveNext();  调用MoveNext方法

        5.MoveNext如何执行:先获取一个状态  ---继续往后执行

        6.如果有异常---一抛出异常--把状态重置为-2

        7.如果没有异常,把状态重置重置为-2

        8.SetResult();---把结果包裹成一个Tsak

 

IAsyncStateMachineBox stateMachineBox = GetStateMachineBox(ref stateMachine, ref taskField); 就是把状态机打包--装到盒子中

 

小结:

  async方法在编译后会生成一个状态机(实现了IAsyncStateMachine接口)

状态机:初始化状态0--执行就修改状态1--再执行就修改状态0---执行就修改状态1---如果出现其他状态就结束

async方法里面的逻辑其实都放在了MoveNext---主线程new一个状态机状态-1、

----主线程调用MoveNext---执行了await之前的任务,然后启动新的Task---主线程改状态为0--回去干自己的事儿-----

子线程再去MoveNext---状态又回归-1----再执行后续的逻辑--如果需要还可以继续循环