簡體   English   中英

為什么Task.WhenAll偶爾需要很長時間

[英]Why does Task.WhenAll occasionally take a long time

我有一個運行少量請求的ASP.NET站點(在3台服務器上分配約500 rpm的請求),通常這些請求大約需要15毫秒。 但是,我發現經常有一些請求花費更長的時間(1秒或更長時間)。 我已將延遲范圍縮小到對Task.WhenAll的調用。 這是令人反感的代碼的示例:

var taskA = dbA.GetA(id);
var taskB = dbB.GetB(id);
var taskC = dbC.GetC(id);
var taskD = dbD.GetD(id);

await Task.WhenAll(taskA, taskB, taskC, taskD);

每個單獨的任務都經過測量,耗時不到10ms。 我已經將延遲確定為Task.WhenAll調用,這似乎與任務的計划方式有關。 據我所知,TPL任務池沒有太大壓力,所以我對性能如此零散的原因感到困惑。

創建線程會增加開銷。 根據您的操作,您還可以嘗試Parallel.ForEach。

public static void yourMethod(int id){

    var tasks = new List<IMyCustomType> { new dbA.GetA(id), new dbB.GetB(id), new dbC.GetC(id), new dbD.GetD(id)};

    // Your simple stopwatch for timing
    Stopwatch stopWatch = new Stopwatch();
    stopWatch.Start();

    // For each 'tasks' list item, call 'executeTasks' (Max 10 occurrences)
    // - Processing for all tasks will be complete before 
    //   continuing processing on the main thread
    Parallel.ForEach(tasks, new ParallelOptions { MaxDegreeOfParallelism = 10 }, executeTasks);

    stopWatch.Stop();
    Console.WriteLine("Completed execution in:  " + stopWatch.Elapsed.TotalSeconds);
}

private static void executeTasks(string obj)
{
    // Your task's work here. 
}

異步操作涉及上下文切換,這非常耗時。 不幸的是,並非總是以確定性的方式。 為了加快處理速度,請嘗試為Task.WhenAll調用添加ConfigureAwait(false)前綴,如下所示:

await Task.WhenAll(taskA, taskB, taskC, taskD).ConfigureAwait(false);

這將消除額外的上下文切換,這實際上是服務器端應用程序推薦的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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