簡體   English   中英

Task.ContinueWith回調線程

[英]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.ContinueWithTaskScheduler.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM