2009-12-01 12 views
27

Per un tipo di funzione "informazioni di registro per supporto" mi piacerebbe enumerare e scaricare informazioni sui thread attivi.Ottenere l'elenco dei thread gestiti attualmente attivi in ​​.NET?

Sono ben consapevole del fatto che le condizioni di gara possono rendere queste informazioni semi-inaccurate, ma mi piacerebbe provare a ottenere il miglior risultato possibile, anche se non è preciso al 100%.

Ho esaminato Process.Threads, ma restituisce oggetti ProcessThread, mi piacerebbe avere una collezione di oggetti Thread, in modo che possa registrare il loro nome e se siano thread in background o meno.

Esiste una tale raccolta disponibile, anche se è solo un'istantanea dei thread attivi quando la chiamo?

ie.

Thread[] activeThreads = ?? 

nota, per essere chiari, io non chiedendo Process.Threads, questa collezione mi dà un sacco, ma non tutti di ciò che voglio. Voglio sapere per quanto tempo vengono utilizzati thread specifici nella nostra applicazione (il che significa che dovrò cercare di connettere i due tipi di oggetti in un secondo momento, ma i nomi sono più importanti della CPU per cominciare.)

+0

Sono 'System.Diagnostics.ProcessThreads' direttamente associabili a' System.Threading.Threads'? Il primo è un thread del sistema operativo, in cui quest'ultimo è un thread gestito. –

+1

No, non lo sono. –

+0

Quali informazioni aggiuntive della classe Thread necessarie non sono presenti nella classe ProcessThread? Un ThreadId del sistema operativo non ha una relazione fissa con un thread gestito, poiché un host non gestito può controllare la relazione tra thread gestiti e non gestiti. In particolare, un host sofisticato può utilizzare l'API di hosting CLR per pianificare molti thread gestiti sullo stesso thread del sistema operativo o per spostare un thread gestito tra diversi thread del sistema operativo. – serhio

risposta

14

Se siete disposti a sostituire Thread creazioni della propria applicazione con un altro classe wrapper, detto classe wrapper in grado di monitorare gli attivi e inattivi Thread s per voi. Ecco un guscio minimo praticabile di un tale involucro:

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); 
       } 
      } 
     } 
    } 
} 

e un driver test rapido di esso (nota io non iterare l'elenco delle discussioni, semplicemente ottenere il conteggio nella lista):

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); 
     } 
    } 
} 

Non sai se puoi seguire un percorso simile, ma raggiungerà l'obiettivo se sarai in grado di integrarlo in una fase iniziale di sviluppo.

+0

Grazie, sembra che questa sia la strada che dovrò usare. –

3

È possibile memorizzare le informazioni sui thread in una ricerca durante la creazione di ciascun thread nell'applicazione?

Come ogni thread inizia, è possibile ottenere il suo ID utilizzando AppDomain.GetCurrentThreadId(). Successivamente, è possibile utilizzare questo per il riferimento incrociato con i dati restituiti da Process.Threads.

+1

Beh, questo è quello che devo fare, ma preferirei di no. –

Problemi correlati