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
操作在先前的任务已在线程池线程上完成或被排队到线程池后以同步方式执行(我知道我可以在ContinueWith
操作中使用QueueUserWorkItem
,但我不喜欢这种方法)。
编辑,我想我可以实现自己的TaskScheduler
,并在TryExecuteTaskInline
内检查是否已在线程池线程上,以控制此操作。
ContinueWith
操作将会同步执行”是什么意思?这里的“同步执行”具体指什么?如果前置任务在池线程上运行,这又如何有意义呢? - AaronaughtTaskScheduler
和SynchronizationContext
之间有一些古怪的交互作用,这就是为什么通常使用TaskScheduler.FromCurrentSynchronizationContext
而不是TaskScheduler.Default
的原因。 - AaronaughtTaskCompletionSource
将第三方代码事件进行了包装。该事件可以在任何线程上触发,包括具有同步上下文的线程。我绝不想使用TaskScheduler.FromCurrentSynchronizationContext
。我希望在线程池上处理TaskCompletionSource.Task
的完成。如果已经在线程池上,则希望使用TaskContinuationOptions.ExecuteSynchronously
作为优化,以避免不必要的线程切换。 - avo