C# 为什么 Parallel.ForEach 不运行多个线程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8923230/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 05:11:48  来源:igfitidea点击:

Why isn't Parallel.ForEach running multiple threads?

c#parallel-processing

提问by zzfima

Today i tried do some optimization to foreachstatement, that works on XDocument.

今天我尝试对foreach语句做一些优化,这适用于XDocument.

Before optimization:

优化前:

foreach (XElement elem in xDoc.Descendants("APSEvent").ToList())
{
    //some operations
}

After optimization:

优化后:

Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), elem =>
{
    //same operations
});

I saw that .NET in Parallel.ForEach(...)opened ONLY one thread! As a result the timespan of Parallelwas bigger than standard foreach.

我看到 .NETParallel.ForEach(...)只打开了一个线程!结果 的时间跨度Parallel大于标准foreach

Why do you think .NET only opened 1 thread? Because of locking of file? Thanks

为什么你认为 .NET 只打开了 1 个线程?因为锁定文件?谢谢

采纳答案by grapeot

It's by design that Parallel.ForEach may use fewer threads than requested to achieve better performance. According to MSDN [link]:

Parallel.ForEach 可以使用比请求更少的线程来实现更好的性能。根据 MSDN [链接]

By default, the Parallel.ForEach and Parallel.For methods can use a variable number of tasks. That's why, for example, the ParallelOptions class has a MaxDegreeOfParallelism property instead of a "MinDegreeOfParallelism" property. The idea is that the system can use fewer threads than requested to process a loop.

The .NET thread pool adapts dynamically to changing workloads by allowing the number of worker threads for parallel tasks to change over time.At run time, the system observes whether increasing the number of threads improves or degrades overall throughput and adjusts the number of worker threads accordingly.

默认情况下,Parallel.ForEach 和 Parallel.For 方法可以使用可变数量的任务。例如,这就是 ParallelOptions 类具有 MaxDegreeOfParallelism 属性而不是“MinDegreeOfParallelism”属性的原因。这个想法是系统可以使用比请求更少的线程来处理循环。

.NET 线程池允许并行任务的工作线程数量随时间变化,从而动态适应不断变化的工作负载。在运行时,系统会观察增加线程数量是提高还是降低整体吞吐量,并相应地调整工作线程的数量。

回答by NoDisplay

Yes exactly, Document.Load(...)locks the fileand due to resource contention between threads, TPL is unable to use the power of multiple threads. Try to load the XML into a Streamand then use Parallel.For(...).

是的,Document.Load(...)锁定文件,由于线程之间的资源争用,TPL 无法使用多线程的能力。尝试将 XML 加载到 a 中Stream,然后使用Parallel.For(...).

回答by cvlad

Do you happen to have a single processor? TPL may limit the number of threads to one in this case. Same thing may happen if the collection is very small. Try a bigger collection. See this answerfor more details on how the degree of parallelism is determined.

你碰巧有一个处理器吗?在这种情况下,TPL 可能会将线程数限制为一个。如果集合非常小,可能会发生同样的事情。尝试更大的集合。有关如何确定并行度的更多详细信息,请参阅此答案

回答by SolidSnake

use it like this:

像这样使用它:

int ParallelThreads = 10;
Parallel.ForEach(xDoc.Descendants("APSEvent").ToList(), new ParallelOptions() { MaxDegreeOfParallelism = ParallelThreads }, (myXDOC, i, j) =>
{
 //do whatever you want here 
});

回答by grapeot

From the problem description, there is nothing that explains why the TPL is not spawning more threads.

从问题描述来看,没有什么可以解释为什么 TPL 没有产生更多线程。

There is no evidence in the question that is even the problem. That can be fixed quite easily: you could log the thread id, before you enter the loop, and as the first thingyou do inside your loop.

在这个问题中没有证据甚至是问题。这可以很容易地修复:您可以在进入循环之前记录线程 ID,并且作为您在循环中执行的第一件事

If it is always the same number, it is the TPL failing to spawn threads. You should then try different versions of your code and what change triggers the TPL to serialize everything. One reason could be if there are a small number of elements in your list. The TPL partitions your collection, and if you have only a few items, you might end up with only one batch. This behavior is configurable by the way.

如果它总是相同的数字,则是 TPL 未能产生线程。然后,您应该尝试不同版本的代码,以及哪些更改会触发 TPL 序列化所有内容。一个原因可能是您的列表中有少量元素。TPL 对您的集合进行分区,如果您只有几个项目,则最终可能只有一批。顺便说一下,此行为是可配置的。

It could be you are inadvertedly taking a lock in in the loop, then you will be seeing lots of different numbers, but no speedup. Then, simplify the code until the problem vanishes.

可能是您无意中锁定了循环,然后您会看到许多不同的数字,但没有加速。然后,简化代码,直到问题消失。