gpt4 book ai didi

c# - 在什么情况下 TaskCompletionSource.SetResult() 会同步运行延续?

转载 作者:可可西里 更新时间:2023-11-01 08:37:33 26 4
gpt4 key购买 nike

最初我认为所有的延续都是在线程池上执行的(给定一个默认的同步上下文)。然而,当我使用 TaskCompletionSource 时,情况似乎并非如此。

我的代码看起来像这样:

Task<int> Foo() {
_tcs = new TaskCompletionSource<int>();
return _tcs.Task;
}

async void Bar() {
Console.WriteLine(Thread.Current.ManagedThreadId);
Console.WriteLine($"{Thread.Current.ManagedThreadId} - {await Foo()}");
}

Bar 在特定线程上被调用并且 TaskCompletionSource 保持未设置一段时间,这意味着返回的任务 IsComplete = false。然后一段时间后,同一个线程将继续调用 _tcs.SetResult(x),据我所知,这应该在线程池上运行延续。

但我在我的应用程序中观察到,运行延续的线程实际上仍然是同一个线程,就好像在调用 SetResult 时同步调用延续一样。

我什至尝试在 SetResult 上设置一个断点并跳过它(并在延续中有一个断点),这实际上又继续同步调用延续。

SetResult() 何时立即同步调用延续?

最佳答案

Initially I thought that all continuations are executed on the threadpool (given a default synchronization context). This however doesn't seem to be the case when I use a TaskCompletionSource.

实际上,当使用 await 时,大多数延续是同步执行的。

Marc 的回答很棒;我只是想更详细一点...

TaskCompletionSource<T>默认情况下将在 Set* 时同步运行叫做。 Set*将完成任务在单个方法调用中发出延续。 (这意味着在持有锁的同时调用 Set* 会导致死锁。)

我在那里使用了奇怪的短语“发布延续”,因为它可能会或可能不会实际执行它们;稍后会详细介绍。

TaskCreationOptions.RunContinuationsAsynchronously标志会告诉TaskCompletionSource<T>异步发出延续。这将完成任务(仍由 Set* 立即完成)与发出延续(仅由 Set* 调用触发)分开。所以用 RunContinuationsAsynchronously , 一个 Set* call只会完成任务;它不会同步执行延续。 (这意味着在持有锁的同时调用 Set* 是安全的。)

但回到默认情况,它会同步发出延续。

每个延续有一个标志;默认情况下,延续是异步执行的,但可以通过 TaskContinuationOptions.ExecuteSynchronously 使其同步。 . (请注意 await does use this flag - 链接指向我的博客;从技术上讲,这是一个实现细节,没有正式记录)。

然而,即使ExecuteSynchronously指定,有a number of situations where the continuation is not executed synchronously :

  • 如果有TaskScheduler与延续相关联,该调度程序可以选择拒绝当前线程,在这种情况下,任务排队TaskScheduler而不是同步执行。
  • 如果当前线程被中止,则任务在别处排队。
  • 如果当前线程的堆栈太深,则任务在别处排队。 (这只是一种启发式方法,并不能保证避免 StackOverflowException )。

这是相当多的条件,但通过简单的控制台应用测试,它们都得到了满足:

  • TaskCompletionSource<T>未指定 RunContinuationsAsynchronously .
  • 延续 ( await ) 确实指定了 ExecuteSynchronously .
  • 延续没有 TaskScheduler指定。
  • 目标线程能够继续执行(未中止;堆栈正常)。

作为一般规则,我会说 TaskCompletionSource<T> 的任何用法应指定 TaskCreationOptions.RunContinuationsAsynchronously .就我个人而言,我认为该标志的语义更合适,也不那么令人惊讶。

关于c# - 在什么情况下 TaskCompletionSource.SetResult() 会同步运行延续?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39296587/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com