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);
我试图为此找到答案,但找不到。我想知道的是在哪个线程上调用 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 线程。
编辑:回复
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);