计算Parallel.ForEach使用的线程数

时间:2017-11-16 14:04:13

标签: c# .net multithreading .net-4.0 task-parallel-library

如何确定在Parallel.ForEach(或Parallel.InvokeParallel.For

的特定通话中使用的话题数量?

我知道如何限制最大线程数,例如

Parallel.ForEach(myList, 
                 new ParallelOptions { MaxDegreeOfParallelism = 4 },
                 item => { doStuff(item); });

我知道Task.Parallel库除了使用当前线程之外,还使用一些启发式方法来确定在运行时使用的其他线程池线程的最佳数量。 0和MaxDegreeOfParallelism之间的某个值。

我想知道实际使用了多少线程,用于记录目的:

Stopwatch watch = Stopwatch.StartNew();
Parallel.ForEach(myList, item => { doStuff(item); });
trace.TraceInformation("Task finished in {0}ms using {1} threads", 
       watch.ElapsedMilliseconds, NUM_THREADS_USED); 

我主要希望记录这些数据是为了好奇,并提高我的理解力。它不必100%可靠,因为我不打算将它用于其他任何事情。

有没有办法获得这个数字,没有重大的性能损失?

2 个答案:

答案 0 :(得分:2)

您可以使用(线程安全)列表来存储使用线程的ID并对其进行计数:

ConcurrentBag<int> threadIDs = new ConcurrentBag<int>();
Parallel.ForEach(myList, item => { 
    threadIDs.Add(Thread.CurrentThread.ManagedThreadId);
    doStuff(item); 
});

int usedThreads = threadIDs.Distinct().Count();

这个 会对性能产生影响(特别是ConcurrentBag的线程安全逻辑),但我不知道它有多大。相对效果取决于doStuff自身的工作量。如果该方法只有几个命令,则此线程计数解决方案甚至可以更改使用的线程数。

答案 1 :(得分:0)

DoStuff方法中,您可以添加如下代码

    private void DoStuff(T item)
        {
            Logger.Log($"Item {item.ToString()} was handled by thread # {Thread.CurrentThread.ManagedThreadId}");
            // your logic here
        }