[英]Task.ContinueWith callback thread
我試圖找到答案,但不能。 我想知道的是在哪個線程上調用Task.ContinueWith
委托。 等待我知道它嘗試在捕獲的SynchronizationContext
上運行它,但沒有記錄任何ContinueWith
。
我也試過一個示例程序,雖然看起來它是在Threadpool
線程上調用的,但我懷疑在某些情況下它可能會調用SynchronizationContext
。 也許有人可以提供明確的答案。
這取決於與continuation關聯的調度程序。 默認情況下,通過Current
調度程序調度任務延續, Current
調度程序是與當前正在執行的任務關聯的TaskScheduler
。 如果未在任務中調用ContinueWith
,則Current
將返回Default
調度程序,它是.NET Framework提供的默認TaskScheduler
實例,它將在線程池上調度您的任務。
如果要影響此行為,可以調用其中一個帶有TaskScheduler
參數的ContinueWith
重載。 一種常見的模式是在UI線程上創建continuation時傳遞TaskScheduler.FromCurrentSynchronizationContext()
,因為這會導致在執行時將continuation調度回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());
要解決此問題,您可以使用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);
Task.ContinueWith
在TaskScheduler.Current
上進行調度,除非其中一個可選重載中的參數另有指定。
如果在TaskScheduler.Current
沒有自定義調度程序(很可能),則繼續將在ThreadPool
上運行。
Task.ContinueWith
從不使用SynchronizationContext
除非您使用TaskScheduler
創建一個TaskScheduler.FromCurrentSynchronizationContext
。
您始終可以使用其中一個可用重載明確說明需要哪個TaskScheduler
:
task.ContinueWith(
_ => {},
null,
CancellationToken.None,
TaskContinuationOptions.None,
TaskScheduler.Default); // Scheduled to the ThreadPool
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.