我是.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()
,因为此代码位于非异步的方法中。
为了测试这段代码,我正在向同一局域网上的另一台服务器发出请求。
请求集合超过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请求?有什么我想念的吗?
答案 0 :(得分:2)
TPL不知道如何最好地安排HTTP呼叫。它甚至不知道你正在执行IO。它的启发式不足。
通常,IO的可选并行度需要通过实验确定。您需要编写代码以便使用此最佳DOP。没有任何内置结构可以为您提供精确的DOP。它始终是最大值。
在这里,某些东西超载导致超时。取消例外通常是超时的标志(是的,这是有问题的API设计)。
您可以使用ForEachAsync
。
requests.ForEachAsync(async () => await ProcessAsync(request)).Wait();