为什么Task.WhenAll偶尔需要很长时间

时间:2018-01-23 22:47:29

标签: c# asp.net-mvc task-parallel-library

我有一个运行少量请求的ASP.NET站点(大约500rpm分为3台服务器),通常请求大约需要15ms。但是,我发现经常需要花费更长时间(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);

每项任务都经过测量,完成时间不到10毫秒。我已经将延迟确定为Task.WhenAll来电,似乎与任务的安排方式有关。据我所知,TPL任务池没有太大的压力,所以我不知道为什么表现如此零散。

2 个答案:

答案 0 :(得分:-1)

创建线程需要开销。根据您正在做的事情,您还可以尝试使用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. 
}

答案 1 :(得分:-1)

异步操作涉及上下文切换,这非常耗时。不幸的是,并不总是以确定的方式。为了加快速度,请尝试使用ConfigureAwait(false)为Task.WhenAll调用添加前缀,如下所示:

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

这将消除额外的上下文切换,这是服务器端应用程序的实际推荐方法。