web-dev-qa-db-fra.com

Comment compter la quantité de threads simultanés dans l'application .NET?

Après avoir lu Parallel.ForEach continue de générer de nouveaux threads Je doute toujours que ce soit une méthode correcte pour compter le nombre de threads simultanés?

Ce que je vois, c'est que la méthode compte le nombre d'itérations (boucles) entrées simultanément mais non terminées dans Parallel.ForEach.
Est-ce synonyme du nombre de threads simultanés véhiculant le nombre correct de threads exécutés simultanément?
Je ne suis pas spécialiste mais je peux imaginer que:

  • les threads peuvent être réutilisés pendant que son activité est échangée quelque part pour continuer plus tard.
  • théoriquement, le thread engagé pour une activité de boucle est conservé dans le pool de threads après la fin d'une boucle mais pas réutilisé pour un autre
  • Ou quelles sont les possibilités de déformer la pureté de l'expérience (du dénombrement des fils)?

Quoi qu'il en soit, comment compter directement la quantité de threads en cours d'exécution du processus .NET, de préférence en code (C #)?

Mise à jour:

Donc, si pour suivre le réponse de Jeppe Stig Nielsen et utiliser pour compter

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

alors la sortie est, à la fois en mode Release (threadsCount == 7) et Debug (threadsCount == 15) est très similaire:

[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

Autrement dit, le nombre de threads ne diminue jamais en disant que la méthode citée ci-dessus est incorrect tandis que System.Diagnostics.ProcessThread donne "Class name is not valid at this point"

Mes conclusions sont-elles correctes et pourquoi ne peut-on pas utiliser ProcessThread?

Le code utilisé de l'application console 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<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();
    }
  }
}
21
Fulproof

Il existe différents types de fils, je pense. Les threads du système d'exploitation pour l'application que vous exécutez peuvent être comptés avec:

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

Il semble compter System.Diagnostics.ProcessThread les instances. Vous devez peut-être compter un autre type de fil, comme les "fils gérés", donc je ne suis pas sûr que ma réponse soit ce que vous cherchez.

47
Jeppe Stig Nielsen

Je ne suis pas un spécialiste mais je peux imaginer que les threads peuvent être réutilisés pendant que son activité est échangée quelque part.

Non - à part certains cas très spécifiques (dont vous n'avez certainement pas besoin de vous inquiéter), les threads ne sont pas utilisés de manière réentrante. Le thread sera réutilisé pour exécuter une autre itération (ou une autre tâche) après l'itération actuelle est terminée, mais il ne sera pas demandé de faire autre chose pendant votre code est en cours d'exécution.

Donc, votre approche actuelle est raisonnable, essentiellement.

Quoi qu'il en soit, comment compter directement la quantité de threads en cours d'exécution dans .NET?

Vous pouvez regarder dans perfmon, qui le représentera graphiquement pour vous. (Si le processus est sous votre contrôle, il est plus simple de démarrer le processus mais faites-le attendre l'entrée, puis ouvrez perfmon, ajoutez un compteur à partir des options "Processus", sélectionnez "Thread Count" comme compteur à ajouter et limitez dans le menu déroulant qui vous intéresse. Cliquez sur OK, puis faites démarrer votre processus.)

EDIT: Pour répondre à la mise à jour:

Autrement dit, le nombre de threads ne diminue jamais indiquant que la méthode citée ci-dessus est incorrecte

Non, tout ce que cela montre, c'est que le nombre de threads exécutant activement votre code diminue, mais les threads sont conservés. C'est tout à fait naturel pour un pool de threads.

pourquoi ProcessThread ne peut-il pas être utilisé?

Vous l'utilisez simplement de manière inappropriée. Jeppe a dit que le système était en comptant les instances de ProcessThread alors que votre code essaie d'assigner une classe à une variable:

diagThreadCount=System.Diagnostics.ProcessThread

C'est tout simplement un code invalide. Le message d'erreur montre que le compilateur se rend compte que c'est le nom d'un type, mais vous ne pouvez pas simplement attribuer un nom de type à une variable.

12
Jon Skeet