TaskContinuations与异步lambdas同步运行

c#

如果我们有 aaa 任务,并且为该任务创建一个延续(通过ContinueWithTaskContinuationOptions.RunSynchronously,如果正在执行的方法ContinueWith如下:

static async Task SimpleMethodContinuationAsync(Task antecedentTask, object state)
{
    // some very lightweight, thread-safe synchronous code.
    await Task.Delay(5000); // Simulate async work.
    // continuation of some more very lightweight, thread-safe synchronous code.
}

await-之后的部分会有效释放开始执行任务延续的线程吗?这个续篇的其余部分将在哪个线程上继续?

SynchronizationContext上面的continuation的先行任务没有礼物时会问这个问题,但我听说SynchronizationContext不流经ContinueWith方法调用?真的吗?

回答

我支持 Marc 的评论:你应该避免ContinueWith; 它是一个低级 API,具有潜在危险的默认行为。

等待之后的部分 - 它会有效地释放开始执行任务延续的线程吗?

await会做到这一点,是的。

这个续篇的其余部分将在哪个线程上继续?... 当上述延续的先行任务不存在 SynchronizationContext 时会问这个问题

最有可能的,这将是完成线程池中的线程Task的返回Task.Delay。这是因为await使用TaskContinuationOptions.ExecuteSynchronously(注意:这是一个实现细节;不依赖于此行为)。

我说“最有可能”是因为有些情况下ExecuteSynchronously不会同步执行。这是优化提示,而不是要求。这也适用于await:之前的延续部分:它很可能(不是绝对)在完成先行任务的线程上运行。

但我听说 SynchronziationContext 不流经 ContinueWith 方法调用?真的吗?

ContinueWith在任务级别工作。它有一些流经的逻辑TaskScheduler.Current(IMO 是使此 API 变得危险的一个方面),但不知道SynchronizationContext.

  • @SpiritBob:如果你想异步等待两个并发任务,那么使用`await Task.WhenAll`;如果它们需要在线程池线程上,则使用 `Task.Run`。`StartNew`/`ContinueWith` 将流向当前的任务调度程序,这通常与当前的 `SynchronizationContext` 无关(但它*可以*)。本地方法有帮助,因为`ContinueWith` 在逻辑上通常与`async void` 方法相同,但我不想将逻辑分散到多个方法中;本地方法将逻辑全部保留在一种方法中。
  • 我觉得学习“ContinueWith”的所有细微差别比学习根本不使用它要困难得多
  • @asaf92:我写了一大堆*异步代码,自从`await`问世以来,我总共使用了`ContinueWith`可能有六次。而这一切都是在本地方法存在之前。现在本地方法是 C# 的一部分,我不确定我是否会再次使用 `ContinueWith`。
  • 这就是我对这些任务的延续所做的事情(通过解开先行任务)——通过“Task.WhenAll”等待它们,但我意识到这更像是一个 XY 问题,我刚刚修复了它——它现在可以在没有使用那些讨厌的 `ContinueWith` 方法调用。

以上是TaskContinuations与异步lambdas同步运行的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>