基于任务的异步编程模型 (TAP) 提供了异步代码的抽象化。你只需像往常一样将代码编写为一连串语句即可。就如每条语句在下一句开始之前完成一样,你可以流畅地阅读代码。编译器将执行许多转换,因为其中一些语句可能会开始运行并返回表示正在进行的工作的 Task。
5 `6 g$ O s h5 q( M7 y2 y' q 这就是此语法的目标:支持读起来像一连串语句的代码,但会根据外部资源分配和任务完成时间以更复杂的顺序执行。这与人们为包含异步任务的流程给予指令的方式类似。在本文中,你将通过做早餐的指令示例来查看如何使用 async 和 await 关键字更轻松地推断包含一系列异步指令的代码。* c/ T6 W- x) E& w
其中在使用异步方法中最好不要使用void当做返回值,无返回值也应使用Task作为返回值,因为使用void作为返回值具有以下缺点:/ F. w* n7 R7 y0 k" T: g4 B
- 无法得知异步函数的状态机在什么时候执行完毕
- 如果异步函数中出现异常,则会导致进程崩溃
3 X* H1 X, Q+ k* P( v6 ` 异步函数不应该返回void
" f0 z9 L2 u' g2 T9 k7 W S! q
- static void Main(string[] args)
- {
- try
- {
- // 如果Run方法无异常正常执行,那么程序无法得知其状态机什么时候执行完毕
- Run();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- Console.Read();
- }
- static async void Run()
- {
- // 由于方法返回的为void,所以在调用此方法时无法捕捉异常,使得进程崩溃
- throw new Exception("异常了");
- await Task.Run(() => { });
- }
应该将异步函数返回Task* c% ?- n( r8 B( g+ V2 O! s+ T
- static async Task Main(string[] args)
- {
- try
- {
- // 因为在此进行await,所以主程序知道什么时候状态机执行完成
- await RunAsync();
- Console.Read();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- static async Task RunAsync()
- {
- // 因为此异步方法返回的为Task,所以此异常可以被捕捉
- throw new Exception("异常了");
- await Task.Run(() => { });
- }
注:事件是一个例外,异步事件也是返回void |