2009-12-01 6 views
27

Für eine Funktion "Protokollinformationen für Unterstützung" möchte ich aktive Thread-Informationen auflisten und ausgeben.Liste der derzeit aktiven verwalteten Threads in .NET erhalten?

Ich bin mir der Tatsache bewusst, dass Race Conditions diese Information halb-ungenau machen können, aber ich möchte versuchen, das bestmögliche Ergebnis zu erzielen, auch wenn es nicht 100% genau ist.

Ich schaute auf Process.Threads, aber es gibt ProcessThread-Objekte zurück, ich hätte gerne eine Sammlung von Thread-Objekten, so dass ich ihren Namen protokollieren kann, und ob sie Hintergrund-Threads sind oder nicht.

Gibt es eine solche Sammlung, auch wenn es nur ein Schnappschuss der aktiven Threads ist, wenn ich es nenne?

dh.

Thread[] activeThreads = ?? 

Hinweis, klar zu sein, ich bin nicht über Process.Threads zu fragen, diese Sammlung gibt mir viel, aber nicht alles, was ich will. Ich möchte wissen, wie viel Zeit spezifische benannte Threads in unserer Anwendung derzeit verwenden (was bedeutet, dass ich später die beiden Arten von Objekten betrachten muss, aber die Namen sind wichtiger als die CPU-Zeit).

+0

Sind 'System.Diagnostics.ProcessThreads' direkt mit' System.Threading.Threads' in Verbindung? Ersteres ist ein Betriebssystem-Thread, wobei Letzteres ein verwalteter Thread ist. –

+1

Nein, sind sie nicht. –

+0

Welche zusätzlichen Informationen aus der Thread-Klasse benötigen Sie, die Sie nicht in der ProcessThread-Klasse haben? Ein ThreadId des Betriebssystems hat keine feste Beziehung zu einem verwalteten Thread, da ein nicht verwalteter Host die Beziehung zwischen verwalteten und nicht verwalteten Threads steuern kann. Insbesondere kann ein ausgeklügelter Host die CLR-Hosting-API verwenden, um viele verwaltete Threads für denselben Betriebssystemthread zu planen oder einen verwalteten Thread zwischen verschiedenen Betriebssystemthreads zu verschieben. – serhio

Antwort

14

Wenn Sie die Thread Anwendungen Ihrer Anwendung durch eine andere Wrapper-Klasse ersetzen möchten, kann die Wrapper-Klasse die aktiven und inaktiven Thread s für Sie verfolgen. Hier ist eine minimal bearbeitbar Schale eines solchen Wrapper:

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

und eine schnelle Testfahrer davon (man beachte ich iterieren nicht über die Liste der Themen, lediglich die Zählung in der Liste erhalten):

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

Nicht sicher, ob Sie eine solche Route gehen können, aber es wird das Ziel erreichen, wenn Sie in der Lage sind, in einem frühen Stadium der Entwicklung zu integrieren.

+0

Danke, es sieht so aus, als wäre das die Route, die ich benutzen muss. –

3

Ist es möglich, Thread-Informationen in einem Lookup zu speichern, während Sie jeden Thread in Ihrer Anwendung erstellen?

Wenn jeder Thread startet, können Sie seine ID mit AppDomain.GetCurrentThreadId() abrufen. Später können Sie dies zum Querverweis mit den Daten verwenden, die von Process.Threads zurückgegeben werden.

+1

Nun, es sieht so aus, als ob ich es tun müsste, aber das möchte ich lieber nicht. –

Verwandte Themen