如何使用任务并行库进行大量的HTTP请求

时间:2016-08-06 20:07:10

标签: c# .net parallel-processing

我是.NET框架的任务并行库(通常是多任务和多线程)的新手。 从我读过的文献中,我应该能够创建一堆任务, 运行它们,框架应该负责产生必要的数量 线程根据系统上可用的资源。 我遇到的问题是及时发出数千个HTTP请求。 所以这就是我的代码。

var taskList = new List<Task>();
foreach(var request in requests)
{
     taskList.Add(client.SendAsync(request));
}
Task.WaitAll(taskList.ToArray());

clientSystem.Net.Http.HttpClient个对象。 我正在使用Task.WaitAll(),因为此代码位于非异步的方法中。 为了测试这段代码,我正在向同一局域网上的另一台服务器发出请求。 请求集合超过15,000,因此应为每个对象创建一个任务。 但它只能在抛出一个聚合异常之前运行大约7,000个。内部异常似乎没有什么帮助,仅说明 “任务被取消了” 虽然取消令牌报告没有请求取消。 最近的调用显示为:

,堆栈跟踪不是很有用
  

在System.Threading.Tasks.Task.WaitAll(Task []任务,Int32   millisecondsTimeout,CancellationToken cancellationToken)   在System.Threading.Tasks.Task.WaitAll(Task []任务,Int32   millisecondsTimeout)
  在System.Threading.Tasks.Task.WaitAll(Task []任务)

我也玩过Parallel.Invoke(),但事实证明情况要糟糕得多。

var taskActionList = new List<Action>();
foreach(var request in requests)
{
    taskActionList.Add(() => client.SendAsync(request));
}
Parallel.Invoke(taskActionList.ToArray());

这不会抛出任何异常,但它只运行大约1,300个任务和 代码运行完成。

我的问题是,你如何使用任务并行库来有效地制作 大量的HTTP请求?有什么我想念的吗?

1 个答案:

答案 0 :(得分:2)

TPL不知道如何最好地安排HTTP呼叫。它甚至不知道你正在执行IO。它的启发式不足。

通常,IO的可选并行度需要通过实验确定。您需要编写代码以便使用此最佳DOP。没有任何内置结构可以为您提供精确的DOP。它始终是最大值。

在这里,某些东西超载导致超时。取消例外通常是超时的标志(是的,这是有问题的API设计)。

您可以使用ForEachAsync

requests.ForEachAsync(async () => await ProcessAsync(request)).Wait();