也许我没有理解对......所有的Parallel类问题:(
但是根据我现在阅读的内容,我了解到当我使用 Parallel 时,我实际上调动了线程池中存在的所有线程来执行某些任务/任务。
例如:
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
DoSomething(someString);
});
因此,在这种情况下,Parallel.ForEach 调动线程池中存在的所有线程以执行“DoSomething”任务/任务。
但是调用 Parallel.ForEach 会创建任何新线程吗?
很明显不会有1000个新线程。但是让我们假设有 1000 个新线程,在某些情况下 threadPool 释放它持有的所有线程,在这种情况下......Parallel.ForEach 将创建任何新线程?
最佳答案
简短回答:Parallel.ForEach()
不会“调动所有线程”。任何在 ThreadPool
上安排一些工作的操作(Parallel.ForEach()
所做的)都可能导致在池中创建新线程。
长答案:要正确理解这一点,您需要了解三个抽象级别的工作原理:Parallel.ForEach()
、TaskScheduler
和 ThreadPool
:
Parallel.ForEach()
(和Parallel.For()
)在TaskScheduler
上安排他们的工作。如果您没有明确指定调度程序,the current one将会被使用。Parallel.ForEach()
将工作拆分到多个Task
之间。每个Task
将处理输入序列的一部分,完成后,它将请求另一部分(如果可用),依此类推。Parallel.ForEach()
将创建多少个Task
?TaskScheduler
将让它运行。这样做的方式是每个Task
在开始执行时首先将其自身的副本排入队列(除非这样做会违反MaxDegreeOfParallelism
,如果您设置了它)。这样,实际的并发级别取决于TaskScheduler
。此外,如果
TaskScheduler
支持,第一个Task
实际上会在当前线程上执行(这是使用RunSynchronously()
完成的)。The default
TaskScheduler
简单地将每个Task
排入ThreadPool
队列。 (实际上,如果从另一个Task
开始一个Task
会更复杂,但这与这里无关。)其他TaskScheduler
可以做完全不同的事情事情和其中一些(如TaskScheduler.FromCurrentSynchronizationContext()
)完全不适合与Parallel.ForEach()
一起使用。ThreadPool
使用相当复杂的算法来决定在任何给定时间应该运行多少线程。但这里最重要的是调度新工作项可以导致创建新线程(尽管不一定立即)。而且因为使用Parallel.ForEach()
,总会有一些项目排队等待执行,这完全取决于ThreadPool
的内部算法来决定线程数。
综合起来,几乎不可能决定 Parallel.ForEach()
将使用多少线程,因为它取决于许多变量。两种极端都是可能的:循环将在当前线程上完全同步运行,并且每个项目将在其自己的新创建线程上运行。
但一般来说,它应该接近最佳效率,您可能不必担心所有这些细节。
关于c# - 使用 System.Threading.Tasks.Parallel 在线程池中创建新线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10850099/