Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用System.Threading.Tasks.Parallel在线程池中创建新线程?_C#_.net_Clr_Task Parallel Library - Fatal编程技术网

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()中的代码阻塞或运行很长时间,那么会有超过内核数量的线程被删除