如何计算.NET应用程序中的并发线程数量?

阅读Parallel.ForEach后继续产生新线程我仍然怀疑它是否是计算并发线程数的正确方法?

我看到的是,该方法计算Parallel.ForEach中同时输入但未完成的迭代(循环)的数量。
它是传递正确数量的同时运行线程的并发线程数的同义词吗?
我不是专家,但我可以想象:

  • 线程可以重新使用,而其活动在某处交换以便以后继续。
  • 从理论上讲,用于循环活动的线程在循环完成后保留在线程池中,但不会重新用于另一个循环
  • 或者有什么可能扭曲实验的纯度(线程计数)?

无论如何,如何直接计算.NET进程的运行线程数,最好是(C#)代码?

更新:

所以,如果要遵循Jeppe Stig Nielsen的回答并使用计数

 directThreadsCount = Process.GetCurrentProcess().Threads.Count; 

然后输出,在Release(threadsCount == 7)和Debug(threadsCount == 15)模式下非常相似:

 [Job 0 complete. 2 threads remaining but directThreadsCount == 7 [Job 1 complete. 1 threads remaining but directThreadsCount == 7 [Job 2 complete. 2 threads remaining but directThreadsCount == 7 [Job 4 complete. 2 threads remaining but directThreadsCount == 7 [Job 5 complete. 2 threads remaining but directThreadsCount == 7 [Job 3 complete. 2 threads remaining but directThreadsCount == 7 [Job 6 complete. 2 threads remaining but directThreadsCount == 7 [Job 9 complete. 2 threads remaining but directThreadsCount == 7 [Job 7 complete. 1 threads remaining but directThreadsCount == 7 [Job 8 complete. 0 threads remaining but directThreadsCount == 7 FINISHED 

也就是说,线程的数量并没有减少,这表明上面提到的方法不正确, System.Diagnostics.ProcessThread给出了"Class name is not valid at this point"

我的结论是否正确,为什么不能使用ProcessThread

使用的C#控制台应用程序代码:

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Edit4Posting { public class Node { public Node Previous { get; private set; } public Node(Node previous) { Previous = previous; } } public class Edit4Posting { public static void Main(string[] args) { int concurrentThreads = 0; int directThreadsCount = 0; int diagThreadCount = 0; var jobs = Enumerable.Range(0, 10); Parallel.ForEach(jobs, delegate(int jobNr) { int threadsRemaining = Interlocked.Increment(ref concurrentThreads); int heavyness = jobNr % 9; //Give the processor and the garbage collector something to do... List nodes = new List(); Node current = null; //for (int y = 0; y < 1024 * 1024 * heavyness; y++) for (int y = 0; y < 1024 * 24 * heavyness; y++) { current = new Node(current); nodes.Add(current); } //******************************* //uncommenting next line gives: "Class name is not valid at this point" //diagThreadCount=System.Diagnostics.ProcessThread directThreadsCount = Process.GetCurrentProcess().Threads.Count; //******************************* threadsRemaining = Interlocked.Decrement(ref concurrentThreads); Console.WriteLine( "[Job {0} complete. {1} threads remaining but directThreadsCount == {2}", jobNr, threadsRemaining, directThreadsCount); }); Console.WriteLine("FINISHED"); Console.ReadLine(); } } } 

我认为有不同种类的线程。 您正在运行的应用程序的操作系统线程可以计算:

 int number = Process.GetCurrentProcess().Threads.Count; 

它似乎计算System.Diagnostics.ProcessThread实例。 也许你需要计算另一种线程,比如“托管线程”,所以我不确定我的回答是你所寻求的。

我不是专家,但我可以想象线程可以重新使用,而它的活动在某处交换。

不 – 除了一些非常具体的情况(你几乎肯定不需要担心)线程不会重复使用。 在当前迭代完成 ,该线程将被重用以运行另一个迭代(或其他任务),但在代码运行不会要求它执行其他操作。

所以你现在的方法基本上是合理的。

无论如何,如何直接计算.NET中运行线程的数量?

您可以查看perfmon,它将为您绘制图形。 (如果进程在您的控制之下,最简单的方法是启动进程但让它等待输入,然后打开perfmon,从“Process”选项中添加一个计数器,选择“Thread Count”作为要添加的计数器,并限制它是您从下拉列表中感兴趣的过程。点击OK,然后让您的流程开始工作。)

编辑:要回答更新:

也就是说,线程的数量并没有减少,这表明上面引用的方法是不正确的

不,它显示的是,主动运行代码的线程数减少了,但线程保持不变。 这对于线程池来说是完全自然的。

为什么不能使用ProcessThread

你只是不恰当地使用它。 Jeppe说系统正在计算ProcessThread的实例,而你的代码试图将一个类分配给一个变量:

 diagThreadCount=System.Diagnostics.ProcessThread 

那只是无效的代码。 错误消息显示编译器意识到它是类型的名称,但您不能只为变量分配类型名称。