2009-12-01 18 views
27

Para un tipo de función de "información de registro para soporte", me gustaría enumerar y volcar información de hilo activo.Obteniendo la lista de hilos actualmente activos administrados en .NET?

Soy consciente de que las condiciones de carrera pueden hacer que esta información sea poco precisa, pero me gustaría tratar de obtener el mejor resultado posible, incluso si no es 100% exacto.

Miré Process.Threads, pero devuelve los objetos ProcessThread, me gustaría tener una colección de objetos Thread, para que pueda registrar su nombre, y si son hilos de fondo o no.

¿Existe tal colección disponible, aunque solo sea una instantánea de los hilos activos cuando la llamo?

es decir.

Thread[] activeThreads = ?? 

Nota, para ser claro, no estoy preguntando por Process.Threads, esta colección me da mucho, pero no todo lo que quiero. Quiero saber cuánto tiempo están usando los hilos específicos específicos de nuestra aplicación (lo que significa que tendré que considerar conectar los dos tipos de objetos más adelante, pero para empezar, los nombres son más importantes que el tiempo de la CPU).

+0

¿'System.Diagnostics.ProcessThreads' se relacionan directamente con' System.Threading.Threads'? El primero es un hilo del sistema operativo, mientras que este último es un hilo gestionado. –

+1

No, no lo son. –

+0

¿Qué información adicional de la clase Thread necesita que no tenga en la clase ProcessThread? Un ThreadId de sistema operativo no tiene una relación fija con un subproceso administrado, porque un host no administrado puede controlar la relación entre subprocesos administrados y no administrados. Específicamente, un host sofisticado puede usar la API CLR Hosting para programar muchos hilos administrados contra el mismo hilo del sistema operativo, o para mover un hilo administrado entre diferentes subprocesos del sistema operativo. – serhio

Respuesta

14

Si usted está dispuesto a sustituir Thread creaciones de su aplicación con otra clase de contenedor, dicho contenedor de clase puede realizar un seguimiento de los activos e inactivos Thread s para usted. Aquí hay una concha mínimo viable de una envoltura tales:

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

y un conductor de prueba rápida de la misma (en cuenta que no iterar sobre la lista de temas, simplemente obtener el recuento de la 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); 
     } 
    } 
} 

No estoy seguro de si puede tomar esa ruta, pero logrará el objetivo si puede incorporarse en una etapa temprana de desarrollo.

+0

Gracias, parece que esta es la ruta que tendré que usar. –

3

¿Es factible que almacene información de subprocesos en una búsqueda a medida que crea cada subproceso en su aplicación?

A medida que se inicia cada subproceso, puede obtener su ID usando AppDomain.GetCurrentThreadId(). Más tarde, puede usar esto para hacer una referencia cruzada con los datos devueltos desde Process.Threads.

+1

Bueno, eso es lo que parece que tengo que hacer, pero prefiero no hacerlo. –

Cuestiones relacionadas