-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathawait & async
92 lines (53 loc) · 5.4 KB
/
await & async
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
await 运算符应用于异步方法中的任务,在方法的执行中插入挂起点,直到所等待的任务完成。 任务表示正在进行的工作。
Pasted from <https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/await>
如何理解这个定义:
1) await 运算符应用于异步方法中的任务
2) await 会在方法的执行中插入挂起点
3) await 会等待任务完成
4) 任务表示正在进行的工作,其实是对任务的解释
什么是异步方法?同步方法?
同步方法:调用同步方法后,在程序继续执行之前需要等待同步方法执行完毕。
异步方法:调用异步方法后立即返回以便程序在异步方法完成其任务的同时执行其他操作。
阻塞(pend)就是任务释放CPU,其他任务可以运行,一般在等待某种资源或信号量的时候出现。挂起(suspend)不释放CPU,如果任务优先级高就永远轮不到其他任务运行,一般挂起用于程序调试中的条件中断,当出现某个条件的情况下挂起,然后进行单步调试。
挂起是一种主动行为,因此恢复也应该要主动完成,而阻塞则是一种被动行为,是在等待事件或资源时任务的表现,你不知道他什么时候被阻塞(pend),也就不能确切 的知道他什么时候恢复阻塞。
Pasted from <https://www.cnblogs.com/jason-liu-blogs/archive/2012/12/19/2825202.html>
异步如何实现?
实现异步的办法:通过创建一个新的线程,线程接收一个同步方法,启动线程,执行方法上的操作。
如何实现异步方法?
在方法内,创建一个线程,该线程接收一个同步方法,启动线程。
异步方法有一个问题,那就是异步方法执行完后,往往还需要下一步操作,我怎么知道异步方法什么时候执行完呢?
解决的办法是传递给异步方法一个回调方法,告诉它,异步执行完后,调用回调方法
如何通过await和async来实现呢?
从code运行效果来看,通过delegate和await是等同的,也就是说 第二种方法会创建出一个同步方法。
那么这个过程中是谁在起作用?await?async?await&async ?
通过测试不加await关键字会发现,如果只是单纯只使用async的话其实和同步方法没有什么区别。
另外一种情况,如果await出现在async修饰的方法中,但是await修饰的方法不是一个异步操作,这样也是不会起作用。
只有await出现在async修饰的方法中并且是在异步操作之前才会转化为异步方法执行。
同一个async 修饰的方法可以出现多个await吗?
async中的线程和主线程有何关联?
多个await修饰的方法的线程是同一个吗?为什么?
通过一些例子发现同一个async 修饰的方法可以出现多个await,在await关键字前面执行的code与主线程是同一线程,但是在await之后运行的code却不在同一线程!!
这个导致线程争用资源的问题,也就是说看似同一处的代码,会运行在不同线程,并且有可能并行。如果访问公共资源(如静态变量)还需要加锁。
为什么会导致这个情况?
这个不知道,有待研究。但是我推测是因为这个时候主线程已经执行完毕给释放了,所以只能在异步线程上执行后续的code了。具体可以分析await下执行流程:
分析下await的执行流程:
异步方法的流执行特点:
1. 异步执行 await 表达式的任务。
2. await 表达式执行完成,继续执行后续部分。如再遇到 await 表达式,按相同情况进行处理。
3. 到达末尾或遇到 return 语句时,根据返回类型可以分三种情况:
a.void:退出控制流。
b.Task:设置 Task 的属性并退出。
c.Task<T>:设置 Task 的属性和返回值(Result 属性)并退出。
4. 同时,调用方法将继续执行,从异步方法获取 Task 对象。需要值的时候,会暂停等到 Task 对象的 Result 属性被赋值才会继续执行。
另外如果同时存在多个串行await修饰的方法那么它们都是运行在第一await产生的异步线程之上。
我的猜想是:当第一次运行到await时会去线程池中寻找是否有空闲线程,如果没有就起一个新线程,之后运行的之后同样去线程池中找空闲线程,前面已经创建了并且现在是空闲的,后面就不需要创建了。
最后总结一下:
在某个异步方法中,如果在某个"任务"在前面有await关键字修饰,那么一旦运行到这个"任务"的时候,会在这个异步方法中插入一个挂起点,一直等待"任务"完成为止。
await 真正的目的只有一个 在调用异步方法时挂起此方法,它认为这个方法是比较耗时的方法,主线程或调用此方法的线程不要在此方法等待。
并同时作个标记,当前执行的线程运行结束时,将由此处恢复运行,所以在await 标记的异步方法下面的代码或方法将不能运行,必须等待这个方法完成!
await只能出现在异步方法中,并且只能用在"任务"的前面
await会在出现的地方插入挂起点
await会一直等待,知道任务完成之后才继续往下执行
async和await同时作用的时候才有可能是异步方法。
在await之后执行的code是在异步线程中执行的,所以千万当心!!
异步方法命名要以Async结尾,这是命名习惯。