C# Async、Await原理

发布时间 2023-09-14 11:38:05作者: 蛋蛋十二月

1、使用异步编程需要async和await:

  • Task 任务可以使用aweit

  • 匿名方法 (包括Lambda表达式) ,通过async也可以变成异步方法

2、加async await表示这个方法可以异步顺序执行。(不加await会出现并行执行)

3、async +await函数调用不会造成阻塞,它内部所有的await阻塞都被封装在一个 异步对象中异步执行。

任务和线程的区别:
1、任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。

2、任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,
这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。

  //Task.Run 本质还是开启一个线程。
  //任务是架构在线程池之上的,也就是说任务最终还是要抛给线程去执行。
  //当方法返回类型为void类型时。使用Task类型返回

优点:当程序需要大量耗时操作,如网络请求,查询数据等就需要用到Task,开启一个任务来执行。

从而避免影响主线程UI界面假死。 在任务请求过程中需要使用 aweit等待任务返回的结果。然后在执行下一步。

任务(不加aweit会出现并行执行),会导致请求的结果未拿到,就执行下面的代码,从而引发异常。

async, await 底层是状态机, 而如果返回值是void的话,调度方是不会有等待行为的,因为没有awaiter

总结一:

  • async的方法会被C#编译器编译成一个类,会主要根据await调用进行切分为多个状态,对async方法的掉用会被拆分
  • 为对MoveNext()的调用。
  • 用await看似时“等待”,经过编译后,其实没有“wait()”

总结二:

await调用的等待时间,.net会把当前的线程返回给线程池(避免占用线程,影响并发),等异步方法执行完成之后,框架会从线程池中在取得一个线程执行后续的代码。

线程池是如何分配线程的?

​ 答:当这个异步方法耗时,速度很慢时,那个线程池就会收回这个线程。当这个异步方法执行完成之后,线程池会在取一个

线程执行后续代码。 而当这个异步方法执行速度很快,那么线程池就不会收回线程。也不会分配线程。

总结三:

​ Task的方法返回值,不一定每一步都标记async , 只需要最后调用时候使用(避免async 重复拆装箱)

异步方法是怎么运作的:

C#编译器一旦遇到以async声明的方法(即异步方法)时会在这个方法中尝试寻找await关键字,如果找到以await关键字声明的方法,就会自动生成一些代码,这些代码负责启动后台线程,尝试找到空闲的CPU内核运行以await声明的方法(即以异步方式运行),完成这一切后调用者线程从异步方法返回。后台线程在运行完以await声明的方法后会结束,此时await关键字生成的代码还负责提取方法的返回结果,所以干活的都是await,async实际上只是提醒编译器"你看到有async关键字的方法时进去方法内部是不是有个await关键字,有的话就干活"。

**C# 异步 await的原理 使用了OnCompleted 回调函数 **

await是什么意思 [两层思想]

  1. Task.Wait()和await`混为一谈,这是错的
  2. await在控制异步的执行次序
  3. await有等待结果的含义
提到await,就得先说说Wait。

字面意思,Wait就是等待。

前边说了,异步有一个核心,是Task。而Task有一个方法,就是Wait,写法是Task.Wait()。所以,很多人把这个Wait和await混为一谈,这是错的。

这个问题来自于Task。C#里,Task不是专为异步准备的,它表达的是一个线程,是工作在线程池里的一个线程。异步是线程的一种应用,多线程也是线程的一种应用。Wait,以及Status、IsCanceled、IsCompleted、IsFaulted等等,是给多线程准备的方法,跟异步没有半毛钱关系。当然你非要在异步中使用多线程的Wait或其它,从代码编译层面不会出错,但程序会。

尤其,Task.Wait()是一个同步方法,用于多线程中阻塞等待。

在那个「同步方法中调用异步方法」的文章中,用Task.Wait()来实现同步方法中调用异步方法,这个用法本身就是错误的。 异步不是多线程,而且在多线程中,多个Task.Wait()使用也会死锁,也有解决和避免死锁的一整套方式。

再说一遍:Task.Wait()是一个同步方法,用于多线程中阻塞等待,不是实现同步方法中调用异步方法的实现方式。
https://www.cnblogs.com/tiger-wang/p/13357981.html

Task.Wait()是一个同步方法,用于多线程中阻塞等待,不是实现同步方法中调用异步方法的实现方式。

https://www.zhihu.com/question/58922017/answer/1358059753