Task与异步
.NET 执行异步有哪三种模式?
-
基于任务的异步模式 (TAP, Task-based Asynchronous Pattern)
- 核心类型:
Task、Task<T> - 关键字:
async/await - 特点:
- 使用
async标记异步方法,await等待任务完成。 - 非阻塞调用,自动处理上下文切换(如 UI 线程不卡死)。
- 通过
Task.Run将同步代码卸载到线程池。
- 使用
- 核心类型:
-
基于事件的异步模式 (EAP, Event-based Asynchronous Pattern) (旧版 .NET 2.0+,已过时)
- 核心类型:
BackgroundWorker、WebClient - 特点:
- 通过事件(如
Completed)通知异步操作结果。 - 需要手动注册事件回调。
- 通过事件(如
- 核心类型:
-
异步编程模型 (APM, Asynchronous Programming Model) 最早期模式,.NET 1.1,已过时)
- 核心类型:
IAsyncResult、BeginXXX/EndXXX方法对。 - 特点:
- 使用
BeginOperation启动异步操作,EndOperation获取结果。 - 需手动处理回调或轮询。
- 使用
- 核心类型:
请简述async 函数的编译方式?
async/await是C# 5.0推出的异步代码编程模型,其本质是编译为状态机。只要函数前带上async,就会将函数转换为状态机。
具体在实际编码中怎么用呢?举个例子:
小明早上起床要吃早餐:要刷牙洗脸(2分钟),要冲牛奶(5分钟),要煎鸡蛋(3分钟),然后所有都准备好了,开吃.
如果这个需求以同步的方式进行,总共会花10分钟,才能成功吃到早餐.
但是在函数上添加async,在刷牙洗脸,冲牛奶,煎鸡蛋前添加await,因为是同步执行,并等待所有线程执行完成,就可以成功吃到早餐,只需要5分钟.
还有一种情况:在函数上添加async,在刷牙洗脸,冲牛奶,煎鸡蛋前不添加await,这样函数里的要干的事情,将不会阻塞,直接2分钟就跳出函数.但是不能成功吃到早餐.因为未添加await,函数结束后,不能保证所有动作都执行完成.
写出控制台输出的字符串顺序
先看一个例子(来源)
执行结果如下: 使用await关键字来调用返回任务的异步方法SayHiAsync,而使用await需要有用async修饰符声明的方法,在SayHiAsync方法为完成前,下面的方法不会继续执行。但是主线程并没有阻塞,且任务处理完成后await后的逻辑继续执行。
- 本质: 编译器将await关键字后的所有代码放进了延续(ContinueWith)方法的代码块中来转换await关键词。
- 注意:
- 无法等待具有void返回类型的异步方法,并且无效返回方法的调用方捕获不到异步方法抛出的任何异常。 async void 应仅用于事件处理程序。因为事件不具有返回类型(因此无法返回 Task 和 Task)。
- 异步方法无法声明 in、ref 或 out 参数,但可以调用包含此类参数的方法。 同样,异步方法无法通过引用返回值,但可以调用包含 ref 返回值的方法。