Async/awit详解(一)
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一起使用。
- async和await一起使用
注意:await只能放在Task前面
await后面的代码会等着task任务的完成后再继续执行
其实就像把await后面的代码包装成一个continuwith的回调动作
然后这个回调动作可能新的子线程,也可能是主线程
以下代码执行过程:主线程开始执行打印------开启一个task线程执行任务----线程还在执行任务,主线程不等待继续往下执行
碰到await task等待task里的任务执行完成然后往下执行最后一句打印,这个可能是主线程执行的,也可能是子线程执行的还可能是一
个新的线程执行的
- awit Task.run()
此时执行过程则是,主线程返回先做完自己的任务,然后再去开启线程执行任务(不阻塞),执行SumFactory111的打印
继续往下执行,又碰到了await 再次返回,完成第一个Task里的任务之后再去创建线程执行
注意:awit Task.run()等待之后,会把Task的任务执行完成,再往下执行,平常时Task里的任务还未执行完成就会往下执行
Async/await的好处
1 主线程(或子线程)遇见await就返回,非阻塞,去做自己的事,await后面新的线程也开始处理自己的任务
这两者之间是并发执行的
2 做到控制线程的顺序,其实就是以写同步方法的方式来异步编程
状态机
- 什么是状态机?
--类似于红绿灯: 红灯:停 绿灯:行;
即一个对象在不同的状态可以执行的不同的行为
- 状态机原理解析
在一个普通方法上添加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----再执行后续的逻辑--如果需要还可以继续循环