Har*_*rya 3 .net c# multithreading task task-parallel-library
我试图为此找到答案,但是没有找到。我想知道的是在哪个线程Task.ContinueWith委托上被调用。等待,我知道它会尝试在捕获的SynchronizationContext文件上运行它,但是没有任何文档记录ContinueWith。
我还尝试了一个示例程序,尽管它似乎是在Threadpool线程上调用的,但我怀疑在某些情况下它可能会调用SynchronizationContext。也许有人可以提供明确的答案。
这取决于与延续相关联的调度程序。默认情况下,任务继续是通过与当前执行的任务相关联的Current调度程序进行调度的TaskScheduler。在ContinueWith任务中未调用when时,Current将返回Default调度程序,该调度程序是TaskScheduler.NET Framework提供的默认实例,它将在线程池上调度您的任务。
如果要影响此行为,则可以调用ContinueWith采用TaskScheduler参数的重载之一。TaskScheduler.FromCurrentSynchronizationContext()在UI线程上创建延续时会通过一种常见的模式,因为这将导致在执行时将延续分派回UI线程。
编辑:回复您的评论:如果您从UI线程上运行的延续生成子任务(打算在线程池上运行),则可能出现死锁。在这种情况下,子任务将从父任务继承任务调度程序,该任务调度程序将绑定到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());
Run Code Online (Sandbox Code Playgroud)
要解决此问题,可以使用为子任务StartNew接受TaskScheduler参数的重载并将其传递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);
Run Code Online (Sandbox Code Playgroud)