SynchronizationContext

SynchronizationContext

考虑以下代码:

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/

10-15 00:31