使用 Async 和 Await 的异步编程
- 异步方法的返回值一般是Task<T>,T是真正的返回值类型,Task<int>。惯例:异步方法名字以Async结尾。
- 即使方法没有返回值,也最好把返回值声明为非泛型的Task。
- 调用泛型方法时,一般在方法前加上await关,这样拿到的返回值就是泛型指定的T类型;
- 异步方法的“传染性”: 一个方法中如果有await调用, 则这个方法也必须修饰为async
使用方法
- async可以随便添加,可以不用await
- await只能出现在task前面,但是方法必须声明async,不能单独出现
- await/async之后:
原本没有返回值的可以返回Task
原本返回T类型的,可以返回Task<T>[HttpGet] public async Task<string> GetTestStringAsync() { var result = ""; Console.WriteLine($"线程={Thread.CurrentThread.ManagedThreadId} ---GetTestStringAsync--开始---{DateTime.Now}"); Task task = Task.Run(() => { Console.WriteLine($"线程={Thread.CurrentThread.ManagedThreadId} ---子任务--开始---{DateTime.Now}"); Thread.Sleep(3000); result = "xxxxxxxxxxx"; Console.WriteLine($"线程={Thread.CurrentThread.ManagedThreadId} ---子任务--结束---{DateTime.Now}"); }); await task;// 跳出 GetTestStringAsync 该方法 ,回去主线程了。 //没 await 那么 后面代码 还是 调用线程执行 //加了 await 那么 await后面的代码,相当于包装成了一个回调, 与子任务 公用一个线程。 Console.WriteLine($"线程={Thread.CurrentThread.ManagedThreadId} ---GetTestStringAsync--结束---{DateTime.Now}"); Console.WriteLine("-----------\r\n"); return result; }
效果
await
- 没 await 那么 后面代码 还是 主线程调用
- 加 await 那么 await后面的代码,相当于包装成了一个回调, 与子任务 共用一个线程。
参考文档
https://learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/