2009-12-01 8 views
27

Pour une fonction de type «consigner les informations pour le support», je voudrais énumérer et vider les informations sur les threads actifs. Je suis bien conscient du fait que les conditions de course peuvent rendre cette information semi-inexacte, mais je voudrais essayer d'obtenir le meilleur résultat possible, même si ce n'est pas 100% précis.Récupérer la liste des threads gérés actuellement actifs dans .NET?

J'ai regardé Process.Threads, mais il renvoie des objets ProcessThread, j'aimerais avoir une collection d'objets Thread, afin que je puisse enregistrer leur nom, et s'ils sont des threads d'arrière-plan ou non.

Y at-il une telle collection disponible, même si ce n'est qu'un instantané des threads actifs quand je l'appelle?

ie.

Thread[] activeThreads = ?? 

Remarque, pour être clair, je ne suis pas poser des questions sur Process.Threads, cette collection me donne beaucoup, mais pas tout ce que je veux. Je veux savoir combien de temps les threads nommés spécifiques de notre application utilisent actuellement (ce qui signifie que je devrai regarder la connexion des deux types d'objets plus tard, mais les noms sont plus importants que l'heure du CPU pour commencer.)

+0

Est-ce que 'System.Diagnostics.ProcessThreads' est directement lié à' System.Threading.Threads'? Le premier est un thread OS, où ce dernier est un thread géré. –

+1

Non, ils ne le sont pas. –

+0

Quelles sont les informations supplémentaires de la classe Thread dont vous n'avez pas besoin dans la classe ProcessThread? Un ThreadId du système d'exploitation n'a pas de relation fixe avec un thread géré, car un hôte non géré peut contrôler la relation entre les threads gérés et non gérés. Plus précisément, un hôte sophistiqué peut utiliser l'API CLR Hosting pour planifier de nombreux threads gérés sur le même thread de système d'exploitation ou pour déplacer un thread géré entre différents threads du système d'exploitation. – serhio

Répondre

14

Si vous souhaitez remplacer les créations Thread de votre application par une autre classe wrapper, cette classe wrapper peut suivre les Thread s actifs et inactifs pour vous. Voici une coquille pratique minimale d'un tel emballage:

namespace ThreadTracker 
{ 
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.Threading; 

    public class TrackedThread 
    { 
     private static readonly IList<Thread> threadList = new List<Thread>(); 

     private readonly Thread thread; 

     private readonly ParameterizedThreadStart start1; 

     private readonly ThreadStart start2; 

     public TrackedThread(ParameterizedThreadStart start) 
     { 
      this.start1 = start; 
      this.thread = new Thread(this.StartThreadParameterized); 
      lock (threadList) 
      { 
       threadList.Add(this.thread); 
      } 
     } 

     public TrackedThread(ThreadStart start) 
     { 
      this.start2 = start; 
      this.thread = new Thread(this.StartThread); 
      lock (threadList) 
      { 
       threadList.Add(this.thread); 
      } 
     } 

     public TrackedThread(ParameterizedThreadStart start, int maxStackSize) 
     { 
      this.start1 = start; 
      this.thread = new Thread(this.StartThreadParameterized, maxStackSize); 
      lock (threadList) 
      { 
       threadList.Add(this.thread); 
      } 
     } 

     public TrackedThread(ThreadStart start, int maxStackSize) 
     { 
      this.start2 = start; 
      this.thread = new Thread(this.StartThread, maxStackSize); 
      lock (threadList) 
      { 
       threadList.Add(this.thread); 
      } 
     } 

     public static int Count 
     { 
      get 
      { 
       lock (threadList) 
       { 
        return threadList.Count; 
       } 
      } 
     } 

     public static IEnumerable<Thread> ThreadList 
     { 
      get 
      { 
       lock (threadList) 
       { 
        return new ReadOnlyCollection<Thread>(threadList); 
       } 
      } 
     } 

     // either: (a) expose the thread object itself via a property or, 
     // (b) expose the other Thread public methods you need to replicate. 
     // This example uses (a). 
     public Thread Thread 
     { 
      get 
      { 
       return this.thread; 
      } 
     } 

     private void StartThreadParameterized(object obj) 
     { 
      try 
      { 
       this.start1(obj); 
      } 
      finally 
      { 
       lock (threadList) 
       { 
        threadList.Remove(this.thread); 
       } 
      } 
     } 

     private void StartThread() 
     { 
      try 
      { 
       this.start2(); 
      } 
      finally 
      { 
       lock (threadList) 
       { 
        threadList.Remove(this.thread); 
       } 
      } 
     } 
    } 
} 

et un pilote d'essai rapide de celui-ci (notez que je n'itérer pas sur la liste des discussions, obtenir simplement le compte dans la liste):

namespace ThreadTracker 
{ 
    using System; 
    using System.Threading; 

    internal static class Program 
    { 
     private static void Main() 
     { 
      var thread1 = new TrackedThread(DoNothingForFiveSeconds); 
      var thread2 = new TrackedThread(DoNothingForTenSeconds); 
      var thread3 = new TrackedThread(DoNothingForSomeTime); 

      thread1.Thread.Start(); 
      thread2.Thread.Start(); 
      thread3.Thread.Start(15); 
      while (TrackedThread.Count > 0) 
      { 
       Console.WriteLine(TrackedThread.Count); 
      } 

      Console.ReadLine(); 
     } 

     private static void DoNothingForFiveSeconds() 
     { 
      Thread.Sleep(5000); 
     } 

     private static void DoNothingForTenSeconds() 
     { 
      Thread.Sleep(10000); 
     } 

     private static void DoNothingForSomeTime(object seconds) 
     { 
      Thread.Sleep(1000 * (int)seconds); 
     } 
    } 
} 

Vous ne savez pas si vous pouvez suivre une telle route, mais elle atteindra l'objectif si vous êtes capable de l'incorporer à un stade précoce du développement.

+0

Merci, il semble que ce soit le chemin que je vais devoir utiliser. –

3

Est-il faisable pour vous de stocker des informations de thread dans une recherche que vous créez chaque thread dans votre application?

Lorsque chaque thread démarre, vous pouvez obtenir son ID en utilisant AppDomain.GetCurrentThreadId(). Plus tard, vous pouvez l'utiliser pour faire une référence croisée avec les données renvoyées par Process.Threads.

+1

Eh bien, c'est comme ça que je dois faire, mais je préfère ne pas. –

Questions connexes