Task.ContinueWith 回调线程

Task.ContinueWith callback thread

我试图为此找到答案,但找不到。我想知道的是在哪个线程上调用 Task.ContinueWith 委托。 对于 await,我知道它会尝试 运行 它在捕获的 SynchronizationContext 上,但是 ContinueWith.

没有任何记录

我还尝试了一个示例程序,虽然它似乎是在 Threadpool 线程上调用的,但我怀疑在某些情况下它可能会在 SynchronizationContext 上调用。也许有人可以提供明确的答案。

Task.ContinueWith 安排在 TaskScheduler.Current 上,除非可选重载之一中的参数另有指定。

如果您在 TaskScheduler.Current 中没有自定义调度程序(这很可能),您的继续将 运行 在 ThreadPool

Task.ContinueWith 永远不会使用 SynchronizationContext 除非你用 TaskScheduler.FromCurrentSynchronizationContext.

创建一个 TaskScheduler

您始终可以使用可用的重载之一明确说明需要哪个 TaskScheduler

task.ContinueWith(
    _ => {}, 
    null, 
    CancellationToken.None, 
    TaskContinuationOptions.None, 
    TaskScheduler.Default); // Scheduled to the ThreadPool

这取决于与延续关联的调度程序。默认情况下,任务延续是通过 Current scheduler, being the TaskScheduler associated with the currently executing task. When ContinueWith is not called from within a task, Current will return the Default 调度程序安排的,这是 .NET Framework 提供的默认 TaskScheduler 实例,它将在线程池上安排您的任务。

如果您想影响此行为,您可以调用带有 TaskScheduler 参数的 ContinueWith 重载之一。一个常见的模式是在 UI 线程上创建延续时传递 TaskScheduler.FromCurrentSynchronizationContext(),因为这会导致延续在执行时被分派回 UI 线程。

编辑:回复:如果您从在 UI 线程上继续 运行ning。在这种情况下,子任务将从父任务继承任务调度程序,父任务将绑定到 UI 线程,导致子任务也在 UI 线程上 运行。

Task.Factory.StartNew(() =>
{
    // Do background work.
}).ContinueWith(_ =>
{
    // Update UI, then spawn child task to do more background work...
    Task.Factory.StartNew(() =>
    {
        // ...but child task runs on UI thread!
    });
},
    CancellationToken.None,
    TaskContinuationOptions.None,
    TaskScheduler.FromCurrentSynchronizationContext());

要解决此问题,您可以使用接受子任务的 TaskScheduler 参数的 StartNew 重载,并将 TaskScheduler.Default 传递给它:

    // Update UI, then spawn child task to do more background work...
    Task.Factory.StartNew(() =>
    {
        // ...and child task now runs on the thread pool.
    },
        CancellationToken.None,
        TaskCreationOptions.None,
        TaskScheduler.Default);