C# 使用System.Threading.Tasks.Parallel在线程池中创建新线程?
也许我没有正确地理解它。。。所有平行班问题:( 但从我现在所读的内容来看,我了解到,当我使用并行时,我实际上会为某些任务调动线程池中存在的所有线程 例如:C# 使用System.Threading.Tasks.Parallel在线程池中创建新线程?,c#,.net,clr,task-parallel-library,C#,.net,Clr,Task Parallel Library,也许我没有正确地理解它。。。所有平行班问题:( 但从我现在所读的内容来看,我了解到,当我使用并行时,我实际上会为某些任务调动线程池中存在的所有线程 例如: var arrayStrings = new string[1000]; Parallel.ForEach<string>(arrayStrings, someString => { DoSomething(someString); }); var arrayStrings=新字符串[1000
var arrayStrings = new string[1000];
Parallel.ForEach<string>(arrayStrings, someString =>
{
DoSomething(someString);
});
var arrayStrings=新字符串[1000];
Parallel.ForEach(ArrayString,someString=>
{
DoSomething(someString);
});
因此,本例中的Parallel.ForEach正在为“DoSomething”任务/任务调动线程池中存在的所有线程
但是调用Parallel.ForEach会创建任何新线程吗
显然不会有1000个新线程。但是假设有1000个新线程,在某些情况下线程池会释放它所持有的所有线程,因此,在这种情况下,…Parallel.ForEach将创建任何新线程?Parallel.ForEach不会创建新线程,也不会“调动所有线程”。它使用线程池中数量有限的线程,并将任务提交给线程池以并行执行。在当前的实现中,默认情况下是每个核心使用一个线程。并行根本不处理线程-它将任务调度到任务框架。这样就有一个调度程序,默认调度程序转到线程池。这一个将尝试找到大量线程(在4.5中比在4.0中更好),线程池可能会慢慢地增加新线程 但这不是parallel.foreach;)的function Parallel.ForEach将创建任何新线程
永远不会。正如我所说的,它有1000个foreach,然后它将10.000个任务排成队列。任务工厂调度程序将执行其编程要执行的操作(您可以替换它)。通常,默认情况下-是的,新线程将在合理范围内缓慢出现。我认为您的做法是错误的。 从中可以看出Parallel.ForEach实际上是一种语法糖 Parallel.ForEach基本上可以归结为这样的东西
for (int p = 0; p < arrayStrings.Count(); p++)
{
ThreadPool.QueueUserWorkItem(DoSomething(arrayStrings[p]);
}
for(int p=0;p
线程池负责调度。如果您感兴趣,有一些优秀的文章介绍线程池调度程序在某种程度上的行为,但这与TPL无关。简短回答:
Parallel.ForEach()
不会“调动所有线程”。任何调度线程池
上的某些工作的操作(这是Parallel.ForEach()
所做的)都可能导致在池中创建新线程
详细回答:要正确理解这一点,您需要知道三个抽象级别是如何工作的:Parallel.ForEach()
、TaskScheduler
和ThreadPool
:
Parallel.ForEach()
(和Parallel.For()
)在TaskScheduler
上安排他们的工作。如果没有明确指定计划程序,将使用
Parallel.ForEach()
在多个任务
之间分割工作。每个任务
将处理输入序列的一部分,完成后,如果有一部分可用,它将请求另一部分,依此类推
有多少个Task
s将Parallel.ForEach()
create?多少个TaskScheduler
将让它运行。这样做的方式是每个Task
在开始执行时首先将其自身的一个副本排队(除非这样做会违反,如果您设置它的话)。这样,实际的并发级别取决于任务调度器
此外,如果任务调度器
支持,第一个任务
将实际在当前线程上执行(这是使用)任务
排入线程池
队列即可。(实际上,如果您从另一个任务
启动一个任务
,情况会更复杂,但这与此处无关。)其他任务调度程序
可以执行完全不同的操作,其中一些(如)完全不适合与Parallel.ForEach()
一起使用ThreadPool
使用相当复杂的算法来决定在任何给定时间应该运行多少个线程。但这里最重要的是,调度新工作项可能会导致创建新线程(虽然不一定是立即创建的)。因为使用Parallel.ForEach()
,总是有一些项目排队等待执行,决定线程数量完全取决于ThreadPool
的内部算法Parallel.ForEach()
将使用多少线程,因为这取决于许多变量。两个极端都是可能的:循环将在当前线程上完全同步运行,而每个项目将在其自己的新创建的线程上运行
但一般来说,is应该接近最佳效率,您可能不必担心所有这些细节。-“执行foreach(在Visual Basic中为每个线程)操作,其中迭代可以并行运行。”
new Thread()
将始终创建一个新线程,而不是使用线程池中的线程。您发布的代码将始终创建与集合中项目数量相同的线程。这绝不表示Parallel.ForEach。Parallel.ForEach()
不是建立在线程池
之上的,它是建立在任务调度程序
之上的。而且,它对每个任务
中的代码更聪明,因此每个项目没有一个任务
。另一件事是,您的代码不会阻塞,而是并行的ForEach()
确实如此。这根本不是真的。如果Parallel.ForEach()中的代码阻塞或运行很长时间,那么会有超过内核数量的线程被删除