【发布时间】:2019-05-30 05:53:00
【问题描述】:
考虑以下代码:
var options = new ParallelOptions();
var urls = GetListOfUrls();
Parallel.ForEach(urls, options, url => {
try {
using (HttpClient client = new HttpClient()) {
client.Timeout = TimeSpan.FromMinutes(30);
Task task = client.GetAsync(url);
task.Wait();
}
} catch (Exception exception) {
Console.WriteLine(exception.Message);
}
});
它在具有 8 个内核的 VM 上启动了约 670 个线程。这是正常的吗?我的理解是,TPL 的经验法则是每个核心 25 个线程,这将使其进入 200 个线程的范围。
附:在下面的代码中,GetListOfUrls() 返回一百万个 URL。
【问题讨论】:
-
我不知道你的“经验法则”,你有来源吗?目标是 1 个线程/核心。
-
线程的最大 nr 数为数千,如果 I/O 速度较慢,您将使用 1 个线程/500 毫秒到达那里。
-
根据我的经验,这很正常。如果您的操作阻塞,则 TPL 将启动更多线程,并且许多场景属于 MaxDegreeOfParallelism 的“高级使用场景”:“当线程池的启发式无法确定要使用的正确线程数并可能最终注入太多线程时。例如,在长时间运行的循环体迭代中,线程池可能无法区分合理进度或活锁或死锁,并且可能无法回收为提高性能而添加的线程。“
-
@HenkHolterman 感谢您提供 HttpClient 链接。哇。修复似乎是一种反模式。
标签: c# .net task-parallel-library