杨中科B站视频链接:.NET 6教程,.Net Core 2022视频教程,杨中科主讲_哔哩哔哩_bilibili
同步点餐:一个服务员来记菜
异步点餐:服务员给菜单客户点餐
异步点餐不会提升单个客户点餐的速度
web服务器能够同时服务的请求数量有限
async、await不等于“多线程”
对于不支持的异步方法怎么办?wait()(无返回值);Result(有返回值)。风险:死锁。尽管不用
await、async是语法糖,最终编译成“状态机调用”
async的方法会被C#编译器编译成一个类,会主要根据await调用进行切分为多个状态,对async方法的调用会被拆分为对MoveNext的调用
用await看似是“等待”,经过编译后,其实没有“wait”
为什么要把一个async方法拆分为多个状态然后分为多次调用?异步的可以避免线程等待耗时操作,但是await还是等待呀?
await调用的等待期间,.net会把当前的线程返回给线程池,等异步方法调用执行完毕后,框架会从线程池再取出来一个线程执行后续的代码
Thread.CurrentThread.ManagedThreadId获取当前线程Id。验证:在耗时异步(写入大字符串)操作前后分别打印线程Id。如果写入内容少,会发现线程Id不变,这是因为微软做的优化:到要等待的时候,如果发现已经执行结束了,那就没必要再切换线程了,剩下的代码就继续在之前的线程上继续执行了
异步方法的代码并不会自动在新线程中执行,除非把代码放到新线程中执行
把要执行的代码以委托的形式传递给Task.Run(),这样就会从线程池中取出一个线程执行我们的委托await Task.Run(()=>{//耗时操作代码,可以return返回值})
1、异步方法会生成一个类,运行效率没有普通方法高
2、可能会占用非常多的线程
没有用async的好处:只甩手Task,不“拆完了再装”反编译上面的代码只是普通的方法调用,优点:运行效率更高,不会造成线程浪费
返回值为Task的不一定都标注async,标注async只是让我们可以更方便的await而已
如果一个异步方法只是对别的异步方法调用的转发,并没有太多复杂的逻辑(比如等待A的结果,在调用B;把A调用的返回值拿到内部做一些处理再返回),那么就可以去掉async关键字
如果想在异步方法中暂停一段时间,不要用Thread.Sleep(),因为它会阻塞调用线程,而要用await Task.Delay()。在控制台中没看到区别,但是放到winform程序中就能看到区别了。asp.net core中也看不到区别但是sleep()会降低并发,用点餐举例子
场景:有时需要提前终止任务,比如:请求超时、用户取消请求
很多异步方法都有CancellationToken参数,用于获得提前终止执行的信号
CancellationToken结构体:None:空 bool IsCancellationRequested是否取消 Register(Action callback)注册取消监听 ThrowifCancellationRequested()如果任务被取消,执行到这句话就抛异常
CancellationTokenSource: CancelAfter()超时后发出取消信号 Cancel()发出取消信号 CancellationToken Token
asp.net core开发中,一般不需要自己处理CancellationToken、CancellationTokenSourse这些,只要做到“能转发CancellationToken就转发”即可。asp.net core会对于用户请求中断进行处理
Task类的重要方法:
1、Task
2、Task
3、FromResult()创建普通数值的Task对象
async是提示编译器为异步方法中的await代码进行分段处理的,而一个异步方法是否修饰了async对于方法的调用者来讲没区别,因此对于接口中的方法或者抽象方法不能修饰为async
异步与yield:复习:yield return不仅能都简化数据的返回,而且可以让数据处理“流水线化”,提升性能
在旧版C#中,async方法中不能用yield。从C#8.0开始,把返回值声明为IAsyncEnumerable(不要带Task),然后遍历的时候用await foreach()即可。
static async Task Main(string[] args)
{
await foreach(var s in Test())
{
Console.WriteLine(s);
}
}
static async IAsyncEnumerable Test()
{
yield return "hello";
yield return "yzk";
yield return "youzack";
}
同步:请求进来时服务器会分配一个线程处理该请求,该线程在处理请求时一直处于繁忙状态,并且不能处理其他的请求 异步:请求进来时服务器会分配一个线程处理该请求,该线程在处理请求的同时,可以处理其他的请求
用async/away目的是简化异步编程模式 异步:async/away 如果执行到away时,它会立即返回并且释放该线程,余下的代码会放进一个回调中,耗时操作完成时才会回调执行 同步:就是线程一直占用,直到程序执行完成
异步:线程同一时间可以处理多个请求,防止请求队列和线程池的增长 同步:线程同一时间只能处理一个请求
总结,异步不能提升响应速度,但是可以提升响应能力(吞吐量)
.NET Web应用中为什么要使用async/await异步编程? - 知乎