Task.ContinueWith回调线程 [英] Task.ContinueWith callback thread

查看:245
本文介绍了Task.ContinueWith回调线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图为此找到答案,但是找不到.我想知道的是在哪个线程上调用了Task.ContinueWith委托. 等待,我知道它会尝试在捕获的SynchronizationContext上运行它,但是没有任何文档记录ContinueWith.

I tried to find an answer for this but couldn't. What I was wondering is that on which thread Task.ContinueWith delegate is called. For await I know that it tries to run it on the captured SynchronizationContext but there is nothing documented for ContinueWith.

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

I also tried with a sample program and though it seems it is called on Threadpool thread, I suspect that in some scenario it might call on SynchronizationContext. Maybe someone can provide a definitive answer.

推荐答案

这取决于与延续相关联的调度程序.默认情况下,任务继续是通过 Current 调度程序,是与当前正在执行的任务关联的TaskScheduler.如果未从任务内调用ContinueWith,则Current将返回

This depends on the scheduler that is associated with the continuation. By default, task continuations are scheduled through the 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 scheduler, which is the default TaskScheduler instance provided by the .NET Framework, and which will schedule your tasks on the thread pool.

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

If you want to influence this behaviour, you can call one of the ContinueWith overloads that takes a TaskScheduler parameter. A common pattern is to pass TaskScheduler.FromCurrentSynchronizationContext() when creating continuations on the UI thread, as this would cause the continuation to be dispatched back onto the UI thread when executed.

编辑:回复您的评论:如果您从UI线程上运行的延续生成子任务(打算在线程池上运行),则可能会出现死锁.在这种情况下,子任务将从父任务继承任务调度程序,该任务调度程序将绑定到UI线程,从而导致子任务也可以在UI线程上运行.

Edit: In reply to your comment: The deadlock may arise if you spawn a child task (intended to run on the thread pool) from a continuation running on the UI thread. In such cases, the child task will inherit the task scheduler from the parent task, which would be bound to the UI thread, causing the child task to run on the UI thread too.

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());

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

To resolve this, you can use the StartNew overload that accepts a TaskScheduler parameter for the child task, and pass TaskScheduler.Default to it:

    // 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);

这篇关于Task.ContinueWith回调线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆