Как подсчитать количество параллельных потоков в приложении .NET? - программирование

Как подсчитать количество параллельных потоков в приложении .NET?

Прочитав Parallel.ForEach продолжает создавать новые потоки. Я все еще сомневаюсь, является ли это правильным методом подсчета количества одновременных потоков?

Я вижу, что метод подсчитывает количество одновременно введенных, но не завершенных итераций (циклов) в Parallel.ForEach.
Является ли это синонимом количества параллельных потоков, передающих правильное количество одновременно выполняемых потоков?
Я не специалист, но могу себе представить, что:

  • потоки могут быть повторно использованы, в то время как их активность менялась местами для продолжения позже.
  • теоретически поток, задействованный для активности цикла, сохраняется в пуле потоков после завершения цикла, но не повторно используется для другого
  • Или каковы возможности искажения чистоты эксперимента (подсчета нитей)?

В любом случае, как напрямую подсчитать количество выполняемых потоков .NET-процесса, желательно в (С#) коде?

Обновление:

Итак, если следовать Jeppe Stig Nielsen answer и использовать для count

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?

Используемый код консольного приложения С#:

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();
    }
  }
}
4b9b3361

Ответ 1

По-моему, есть разные виды потоков. Потоки операционной системы для приложения, в котором вы работаете, можно пересчитать с помощью:

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

Кажется, что количество экземпляров System.Diagnostics.ProcessThread. Возможно, вам нужно подсчитать еще один вид потока, например "управляемые потоки", поэтому я не уверен, что мой ответ - это то, что вы ищете.

Ответ 2

Я не специалист, но могу представить, что потоки могут использоваться повторно, а его активность менялась где-то.

Нет - кроме некоторых очень конкретных случаев (о которых вам почти наверняка не нужно беспокоиться), потоки не используются повторно. Поток будет повторно использован для запуска другой итерации (или какой-либо другой задачи) после завершения текущей итерации, но не будет просить сделать что-то еще, пока ваш код запущен.

Итак, ваш нынешний подход разумный, в основном.

В любом случае, как напрямую подсчитать количество запущенных потоков в .NET?

Вы можете посмотреть в perfmon, который отобразит его для вас. (Если процесс находится под вашим контролем, проще всего запустить процесс, но заставить его ждать ввода, затем открыть perfmon, добавить счетчик из параметров "Process", выбрать "Count Thread" в качестве счетчика для добавления и ограничить это к процессу, который вас интересует, из раскрывающегося списка. Нажмите "ОК", а затем запустите свой процесс.)

EDIT: для ответа на обновление:

То есть количество потоков не уменьшается, говоря, что приведенный выше метод неверен

Нет, все это показывает, что количество потоков, активно работающих на вашем коде, уменьшается, но потоки сохраняются. Это совершенно естественно для пула потоков.

почему нельзя использовать ProcessThread?

Вы просто используете его ненадлежащим образом. Джеппе сказал, что система подсчитывает экземпляры ProcessThread, тогда как ваш код пытается назначить класс переменной:

diagThreadCount=System.Diagnostics.ProcessThread

Это просто неверный код. Сообщение об ошибке показывает, что компилятор реализует это имя типа, но вы не можете просто назначить имя типа переменной.