【问题标题】:How to Make Numerous HTTP Requests Using Task Parallel Library如何使用任务并行库发出大量 HTTP 请求
【发布时间】:2016-12-12 23:51:22
【问题描述】:

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

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

client 是一个 System.Net.Http.HttpClient 对象。 我正在使用Task.WaitAll(),因为此代码位于非异步方法中。 为了测试此代码,我向同一 LAN 上的另一台服务器发出请求。 requests 集合有超过 15,000 个,因此应该为每个对象创建一个任务。 但它在引发聚合异常之前只能运行大约 7,000 次。内部异常似乎不是很有帮助,仅说明 “任务被取消” 尽管取消令牌报告未请求取消。 堆栈跟踪也不是很有帮助,最近的调用显示为:

在 System.Threading.Tasks.Task.WaitAll(Task[] 任务,Int32 毫秒超时,CancellationToken 取消令牌) 在 System.Threading.Tasks.Task.WaitAll(任务 [] 任务,Int32 毫秒超时)
在 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 请求?有什么我遗漏的吗?

【问题讨论】:

  • 我担心任务并行库与您尝试的async - await方法无关。
  • 您得到的异常可能是因为某些请求已超时。您在很短的时间内发送了大量请求,您应该预料到会发生这种情况。如果一个请求超时怎么办?此外,您是否应该将任何给定时刻的活动请求数限制为合理的数量,例如10 点?

标签: c# .net parallel-processing


【解决方案1】:

TPL 不知道如何最好地安排您的 HTTP 调用。它甚至不知道您正在执行 IO。它的启发式方法不足。

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

这里,有些东西超载导致超时。取消异常通常表示超时(是的,这是有问题的 API 设计)。

您可以为此使用ForEachAsync

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    • 2019-10-20
    • 2014-08-06
    • 1970-01-01
    相关资源
    最近更新 更多