c# - 使用 System.Threading.Tasks.Parallel 在线程池中创建新线程?

标签 c# .net clr task-parallel-library

也许我没有理解对......所有的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()TaskSchedulerThreadPool:

  1. Parallel.ForEach()(和 Parallel.For())在 TaskScheduler 上安排他们的工作。如果您没有明确指定调度程序,the current one将会被使用。

    Parallel.ForEach() 将工作拆分到多个 Task 之间。每个 Task 将处理输入序列的一部分,完成后,它将请求另一部分(如果可用),依此类推。

    Parallel.ForEach() 将创建多少个TaskTaskScheduler 将让它运行。这样做的方式是每个 Task 在开始执行时首先将其自身的副本排入队列(除非这样做会违反 MaxDegreeOfParallelism ,如果您设置了它)。这样,实际的并发级别取决于 TaskScheduler

    此外,如果 TaskScheduler 支持,第一个 Task 实际上会在当前线程上执行(这是使用 RunSynchronously() 完成的)。

  2. The default TaskScheduler简单地将每个 Task 排入 ThreadPool 队列。 (实际上,如果从另一个 Task 开始一个 Task 会更复杂,但这与这里无关。)其他 TaskScheduler 可以做完全不同的事情事情和其中一些(如 TaskScheduler.FromCurrentSynchronizationContext() )完全不适合与 Parallel.ForEach() 一起使用。

  3. ThreadPool 使用相当复杂的算法来决定在任何给定时间应该运行多少线程。但这里最重要的是调度新工作项可以导致创建新线程(尽管不一定立即)。而且因为使用 Parallel.ForEach(),总会有一些项目排队等待执行,这完全取决于 ThreadPool 的内部算法来决定线程数。

综合起来,几乎不可能决定 Parallel.ForEach() 将使用多少线程,因为它取决于许多变量。两种极端都是可能的:循环将在当前线程上完全同步运行,并且每个项目将在其自己的新创建线程上运行。

但一般来说,它应该接近最佳效率,您可能不必担心所有这些细节。

关于c# - 使用 System.Threading.Tasks.Parallel 在线程池中创建新线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10850099/

相关文章:

c# - .NET:关于 AssemblyVersion,什么定义了二进制兼容性?

c# - 将 log4net 包含到使用 .net 4.0 构建的 .net Web 应用程序中

c# - 如何去除 ToolStrip Winforms 控件一角的这种奇怪的视觉伪像?

C# 从不同的表单类调用方法?

c# - WPF MainWindow 重写 OnStartup

c# - 从 Exchange 的 GetUserAvailability() 结果中获取与会者

c# - 在 C# 中从 Outlook 添加文件夹到 pst 文件

c# - 将一个大字典分成多个部分是否明智?

c# - C# 枚举中的空格

c# - 我可以阻止 CLR 优化掉调试信息吗?