Having read Parallel.ForEach keeps spawning new threads I am still in doubt whether it is a correct method of counting the number of concurrent there threads?
What I see is that method counts the number of simultaneously entered but not completed iterations (loops) in Parallel.ForEach
.
Is it synonym of the number of concurrent threads conveying correct number of simultaneously run threads?
I'm not a specialist but I can imagine that:
- the threads can be re-used while its activity swapped somewhere for continuing later.
- theoretically the thread engaged for a loop activity is kept in thread pool after a loop completion but not re-used for another
- Or what are the possibilities of distorting the purity of experiment (of threads counting)?
Anyway, how to directly count the amount of running threads of .NET process, preferably in (C#) code?
Update:
So, if to follow the Jeppe Stig Nielsen's answer and use for count
directThreadsCount = Process.GetCurrentProcess().Threads.Count;
then output is, both in Release (threadsCount == 7) and Debug (threadsCount == 15) mode is very similar:
[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
That is, the number of threads are not ever decreasing telling that the cited above method is incorrect while System.Diagnostics.ProcessThread
gives "Class name is not valid at this point"
Are my conclusions correct and why cannot ?ProcessThread
be used
The used code of C# console application:
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<Node> nodes = new List<Node>();
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();
}
}
}