考虑以下代码:
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:
在 Albahari 兄弟的书“ C# 5.0 in a Nutshell ”的第 14 章第 588 页中,说明了两个异步操作 task1 和 task2 并行运行。这对我来说似乎不正确。据我了解,当
var task1 = PrintAnswerToLife();
运行时,执行进入 PrintAnswerToLife()
,当它遇到 await
时将执行返回到 Go()
,并继续到下一行 var task1 = PrintAnswerToLife();
,同样的事情再次发生。换句话说,在 Go()
的前两行中没有并行发生任何事情。事实上,除非涉及线程(如 Task.Run()
或 Task.Delay()
),否则不会发生真正的并行性。我是否正确理解了这一点?如果是这样,Albahari 所说的两个操作并行运行的真正含义是什么?问题 2:
在同一页上,阿尔巴哈里继续说明以下内容:
阿尔巴哈里这句话是什么意思?我不明白
SynchronizationContext
在这里是如何发挥作用的,以及它有什么不同。 最佳答案
问题 1:
Parallel usually means multiple threads processing simultaneously. The more accurate term to use here is concurrent. 在您的示例中,两个任务同时执行。这意味着两个任务中的异步操作(即 await Task.Delay(5000)
)同时“执行”。这就是为什么自 Go
开始后两个任务都将完成大约 5 秒的原因。如果任务按顺序运行,则需要 10 秒。然后将在线程池线程上安排同步延续(假设没有特殊的 SynchronizationContext
)并且有机会并行。
是的。
它们与潜在的并行延续并发和异步运行。
问题2:
再次解释有点简单。 指的是特定的 SynchronizationContext
s,GUI 环境 中使用的单线程 SynchronizationContext
s。因为这个 SynchronizationContext
将所有工作安排在一个特定的线程上,所以它不允许“真正的并发”。但是,还有其他多线程 SynchronizationContext
s,您可以创建自己的。因此,使用 SynchronizationContext
并不一定会 阻碍并发(您也可以通过在任务上使用 SynchronizationContext
来完全禁用 ConfigureAwait(false)
捕获)
在 GUI 环境中,SynchronizationContext
使用无法并行执行任何内容的单个线程。
关于c# - 异步和同步上下文,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26327418/