异步编程 async、await
1、使用async修饰符标记的方法称为异步方法
1) 异步方法的返回值一般是Task<T>,T是真正的返回值类型,Task<int>。惯例:异步方法名字以Async结尾。
2) 即使方法没有返回值,也最好把返回值声明为非泛型的Task。
3) 调用泛型方法时,一般在方法前加上await关,这样拿到的返回值就是泛型指定的T类型;
4) 异步方法的“传染性”:一个方法中如果有await调用,则这个方法也必须修饰为async
2、async 方法的缺点
- 异步方法会生成一个类,运行效率没有普通方法高;
- 可能会占用非常多的线程;
3、异步方法使用注意
优化:直接返回异步方法Task<T>,只是当成普通的方法调用,运行效率更高,不会造成线程浪费。
禁用:异步方法Task<T>的 Wait()【无返回值】,Result()【有返回值】,存在死锁风险,尽量不用
优化:await Task.Delay(毫秒数):延迟,不会卡主线程。【异步方法中暂停使用】
禁用:Thread.Sleep(毫秒数):延迟,会阻塞主线程,降低并发。
返回值为Task的不一定都要标注 async ,标注 async 只是让我们更方便 await 而已。
如果一个异步方法只是对别的异步方法调用的转发,并没有太多复杂的逻辑(比如等待A的结果,在调用B,把A调用的返回值拿到内部做一些处理再返回),那么就可以去掉 async 关键字。
4、特殊处理
有时需要提前终止任务比如:请求超时、用户取消请求。
很多异步方法都有CancellationToken 参数,用于获得提前终止执行的信号。
CancellationToken 结构体常用的内容
- bool IsCancellationRequested 是否被取消
- ThrowIfCancellationRequested() 如果异步任务被取消,执行这句话就抛异常。
.Net Core开发中,一般不需要自己处理CancellationToken、CancellationTokenSource这些,只要做到"能转发CancellationToken就转发"即可。