【发布时间】:2014-08-03 17:53:00
【问题描述】:
TaskScheduler.Default不是否总是保证任务将在池线程上执行?
在修复错误时,我发现至少有一种情况没有修复。它可以像这样复制(由真实代码制作的人为示例):
var tcs = new TaskCompletionSource<bool>();
var sc = SynchronizationContext.Current;
sc.Post(_ => tcs.SetResult(true), null);
await tcs.Task.ContinueWith(_ =>
{
// breaks here
Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
还有其他情况吗?
另外,有没有一种优雅的方法来确保ContinueWith 操作同步执行,如果前面的任务已经在池线程上完成,或者排队到线程池中(我知道我可以使用QueueUserWorkItem in ContinueWith 行动,但我不喜欢它)。
已编辑,我想我可以实现自己的 TaskScheduler 并检查我是否已经在 TryExecuteTaskInline 内的线程池线程上,以控制它。
【问题讨论】:
-
“...
ContinueWith动作同步执行,如果前面的任务已在池线程上完成”究竟是什么意思? 同步在这里应该是什么意思?如果先行项在池线程上运行,这怎么可能有意义? -
另外,你说这个repro case 不在池线程上执行,那么它在哪个线程上执行?此代码 sn-p 是否是当前同步上下文是 Winforms 或 WPF 调度程序的 UI 代码的一部分?
TaskScheduler和SynchronizationContext有古怪的交互,这就是为什么你通常使用TaskScheduler.FromCurrentSynchronizationContext而不是TaskScheduler.Default。 -
@Aaronaught,实际代码用
TaskCompletionSource包装了第 3 方代码事件。该事件可以在任何线程上触发,包括具有同步上下文的线程。我绝对不想要TaskScheduler.FromCurrentSynchronizationContext。我想处理线程池上TaskCompletionSource.Task的完成。如果TaskContinuationOptions.ExecuteSynchronously已经在线程池中,我想使用它作为优化,以避免不必要的线程切换。 -
请注意,ExecuteSynchronously 从不保证在同一个线程上同步运行。这是一个提示。
-
@usr,谢谢你的好点。我刚读到什么时候不是:blogs.msdn.com/b/pfxteam/archive/2012/02/07/10265067.aspx
标签: c# .net task-parallel-library async-await task