请考虑以下代码:
async Task Go()
{
var task1 = PrintAnswerToLife();
var task2 = PrintAnswerToLife();
await task1; await task2;
}
async Task PrintAnswerToLife()
{
var task = GetAnswerToLife();
int answer = await task; Console.WriteLine(answer);
}
async Task<int> GetAnswerToLife()
{
var task = Task.Delay(5000);
await task; int answer = 21 * 2; return answer
}
问题1:
在第488页的第14章中,#34; C#5.0 in a Nutshell &#34;由Albahari兄弟声明,两个异步操作task1和task2并行运行。这对我来说似乎不正确。据我所知,当var task1 = PrintAnswerToLife();
运行时,执行进入PrintAnswerToLife()
,当命中await
时,执行返回Go()
,然后进入下一行{{1} ,同样的事情又发生了。换句话说,在var task1 = PrintAnswerToLife();
的前两行中没有任何并行发生。实际上,除非涉及一个线程(如Go()
或Task.Run()
),否则不会发生真正的并行性。我理解正确吗?如果是这样,Albahari说这两个操作并行运行真正意味着什么?
问题2:
在同一页上,Albahari继续陈述以下内容:
无论是否以这种方式创建的并发 操作是在UI线程上启动的,尽管有一个 它是如何发生的差异。在这两种情况下,我们都是一样的 并发发生在启动它的底层操作中 (例如Task.Delay,或者运行到Task.Run的代码)。上面的方法 在调用堆栈中只有在真正的并发时才会受到 在没有同步上下文的情况下启动操作......
阿尔巴哈里的意思是什么?我不明白Task.Delay()
如何在这里发挥作用,以及它有何不同。
答案 0 :(得分:4)
实际上,除非涉及一个线程(如在Task.Run()或中 Task.Delay()),没有真正的并行性发生。我明白了吗 正确?
只有当我们谈论并行时才需要涉及线程。您的示例是关于并发
让我们分解:
您执行PrintAnswerToLife
,而GetAnswerToLife
依次运行await
,然后就会Task.Delay(5000)
点击PrintAnswerToLife
。一旦点击,返回将使控制权返回await
,然后Task<int>
将返回Go
,这将导致执行返回PrintAnswerToLife
。同时,开始执行您对task2
对await
执行相同的循环。
然后依次Task
每个Task.WhenAll
。您可以使用SynchronizationContext
轻松等待同时。
阿尔巴哈里的意思是什么?我不明白怎么回事 SynchronizationContext在这里发挥作用,它有什么区别 使?
SynchronizationContext
负责执行流程。在.NET中,我们有各种DispatcherSynchronizationContext
,例如WinFormSynchronizationContext
和SynchronizationContext
,它们负责将编组工作重新分配到UI线程(分别是WPF和WinForms) )。我认为他试图指出的事实是,SynchronizationContext
中的每一个最终都会将控制权归还给某种UI消息循环,这种循环将被迫一个接一个地同步执行。如果没有ThreadPoolSynchronizationContext
,则使用的默认值是ConfigureAwait(false)
,它将在仲裁线程池线程上调用这些任务的继续。这并非完全正确,因为可以使用{{1}}避免将上下文封送回UI线程。
答案 1 :(得分:2)
Parallel usually means multiple threads processing simultaneously. The more accurate term to use here is concurrent.在您的示例中,两个任务同时执行。这意味着两个任务中的异步操作(即await Task.Delay(5000)
)同时“执行”。这就是为什么两个任务在Go
开始后大约5秒就完成了。如果任务按顺序运行,则需要10秒钟。然后将在线程池线程上调度同步延续(假设没有特殊的SynchronizationContext
)并且存在并行机会。
我是否理解正确?
是
如果是这样,Albahari说这两个操作并行运行真正意味着什么?
它们与可能并行的延续并发和异步运行。
再次解释有点过分了。 它指的是特定的SynchronizationContext
s,GUI环境中使用的单线程SynchronizationContext
。因为这个SynchronizationContext
调度所有工作在一个特定的线程上,所以它不允许“真正的并发”。但是,还有其他多线程SynchronizationContext
,您可以创建自己的。SynchronizationContext
。因此,使用SynchronizationContext
不会必然阻碍并发(并且您还可以通过在任务上使用ConfigureAwait(false)
来完全禁用SynchronizationContext
捕获)
Albahari对此有何意义?
在GUI环境中,{{1}}使用一个不能并行执行任何操作的线程。