也许我不理解它...所有Parallel类问题:(
但是根据我现在正在阅读的内容,我明白当我使用Parallel时,我实际上调动了threadPool中存在的所有线程以执行某些任务/任务。
例如:
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
DoSomething(someString);
});
因此,在这种情况下,Parallel.ForEach正在调动threadPool中存在的所有线程,用于“DoSomething”任务/任务。
但调用Parallel.ForEach会不会创建任何新线程?
很明显,没有1000个新线程。但是我们假设有1000个新线程,有些情况下threadPool会释放它所拥有的所有线程,在这种情况下...... Parallel.ForEach会创建任何新线程吗?
答案 0 :(得分:11)
简短回答:Parallel.ForEach()
没有“动员所有线程”。并且在ThreadPool
(Parallel.ForEach()
执行)上调度某些工作的任何操作都可能导致在池中创建新线程。
答案很长:为了正确理解这一点,您需要了解三个抽象级别的工作原理:Parallel.ForEach()
,TaskScheduler
和ThreadPool
:
Parallel.ForEach()
(和Parallel.For()
)按TaskScheduler
安排工作。如果未明确指定调度程序,则将使用the current one。
Parallel.ForEach()
在几个Task
之间拆分工作。每个Task
将处理输入序列的一部分,一旦完成,它将请求另一个部分(如果有的话),依此类推。
Task
会Parallel.ForEach()
创建多少TaskScheduler
个?尽可能多的Task
让它运行。这样做的方法是每个TaskScheduler
在开始执行时首先将自身的副本排入队列(除非这样做会违反MaxDegreeOfParallelism
,如果你设置的话)。这样,实际并发级别最多为Task
。
此外,如果TaskScheduler
支持,则第一个Task
将在当前线程上执行(这是使用RunSynchronously()
完成的。)
The default TaskScheduler
只需将每个ThreadPool
排入Task
个队列。 (实际上,如果你从另一个Task
开始TaskScheduler
会更复杂,但这里没有相关性。)其他Parallel.ForEach()
可以做完全不同的事情和其中一些(比如{{ 3}})完全不适合与ThreadPool
一起使用。
Parallel.ForEach()
使用相当复杂的算法来确定在任何给定时间应该运行多少线程。但最重要的是,安排新工作项可以导致创建新线程(尽管不一定立即)。因为使用ThreadPool
,总会有一些项目排队等待执行,完全取决于Parallel.ForEach()
的内部算法来决定线程数。
总而言之,确定{{1}}将使用多少线程几乎是不可能的,因为它取决于许多变量。两种极端都是可能的:循环将在当前线程上完全同步运行,并且每个项目将在其自己的新创建的线程上运行。
但一般情况下,应该接近最佳效率,您可能不必担心所有这些细节。
答案 1 :(得分:1)
Parallel.Foreach不会创建新线程,也不会“动员所有线程”。它使用来自线程池的有限数量的线程,并将任务提交给它们以进行并行执行。在当前实现中,默认是每个核心使用一个线程。
答案 2 :(得分:1)
我认为你的方式错了。 从PATTERNS OF PARALLEL PROGRAMMING开始,你会看到Parallel.ForEach真的是语法糖。
Parallel.ForEach很大程度上归结为类似的东西,
for (int p = 0; p < arrayStrings.Count(); p++)
{
ThreadPool.QueueUserWorkItem(DoSomething(arrayStrings[p]);
}
ThreadPool负责调度。如果您感兴趣,有一些关于ThreadPool调度程序在某种程度上如何表现的优秀文章,但这与TPL无关。
答案 3 :(得分:0)
Parallel根本不处理线程 - 它将TASKS安排到任务框架。然后有一个调度程序,默认调度程序进入线程池。这个将尝试找到一个goo数量的线程(4.5比4.0更好)并且Threadpool可能会慢慢启动新线程。
但这不是parallel.foreach的功能;)
Parallel.ForEach将创建任何新线程???
永远不会。正如我所说 - 它有1000个foreach,然后排队10.000个任务,Point。任务工厂调度程序将执行它编程要执行的操作((您可以替换它)。通常,默认 - 是的,慢慢地新线程将在原因中出现。