Obtener lista de hilos

Quiero enumerar todos los subprocesos en ejecución pero no mediante la clase List . Quiero observar dinámicamente los hilos en ejecución. ¿Cómo puedo hacer eso?

 using System.Diagnostics; ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads; foreach (ProcessThread thread in currentThreads) { // Do whatever you need } 

Método 1: obtener hilos del sistema operativo

Esto obtiene la lista de hilos del sistema operativo:

 ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads; foreach (ProcessThread thread in currentThreads) { } 

Método 2: Obtener hilos gestionados

Los hilos gestionados se sientan encima de los hilos del sistema operativo. Los identificadores son diferentes, y en teoría, más de un subproceso administrado se puede ubicar encima de un solo subproceso del sistema operativo (aunque realmente no he observado esto).

Resulta que obtener hilos gestionados es más complicado de lo que realmente debería ser.

Método 2.1: código más simple para obtener hilos gestionados

  1. Consulte Microsoft.Diagnostics.Runtime en GitHub .
  2. Instale el paquete NuGet CLR Memory Diagnostics (ClrMD) .

Luego puede usar dicho paquete NuGet para adjuntarlo a su propio proceso, y leer los hilos administrados:

 using Microsoft.Diagnostics.Runtime; using (DataTarget target = DataTarget.AttachToProcess( Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive)) { ClrRuntime runtime = target.ClrVersions.First().CreateRuntime(); foreach (ClrThread thread in runtime.Threads) { } } 

Método 2.2: Ejemplo de cómo buscar a través de subprocesos administrados por el seguimiento de la stack

Lamentablemente, no pude encontrar ninguna forma de buscar en la lista de hilos por el nombre de la secuencia.

Sin embargo, no todo está perdido: aquí hay un ejemplo de cómo crear un hilo administrado, luego búscalo a través de los marcos de stack para encontrar una coincidencia en el espacio de nombres, luego imprime sus propiedades:

 namespace MyTest { int managedThreadId = 0; var task = Task.Run( () => { // Unfortunately, cant see "Testing" anywhere in result returned // from NuGet package ClrMD ... Thread.CurrentThread.Name = "Testing"; Thread.Sleep(TimeSpan.FromDays(1)); }); // ... so we look for our thread by the first word in this namespace. string startOfThisNamespace = this.GetType().Namespace.ToString().Split('.')[0]; // Is "MyTest". using (DataTarget target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive)) { ClrRuntime runtime = target.ClrVersions.First().CreateRuntime(); foreach (ClrThread thread in runtime.Threads) { IList stackFrames = thread.StackTrace; List stackframesRelatedToUs = stackFrames .Where(o => o.Method != null && o.Method.ToString().StartsWith(startOfThisNamespace)).ToList(); if (stackframesRelatedToUs.Count > 0) { Console.Write("ManagedThreadId: {0}, OSThreadId: {1}, Thread: IsAlive: {2}, IsBackground: {3}:\n", thread.ManagedThreadId, thread.OSThreadId, thread.IsAlive, thread.IsBackground); Console.Write("- Stack frames related namespace '{0}':\n", startOfThisNamespace); foreach (var s in stackframesRelatedToUs) { Console.Write(" - StackFrame: {0}\n", s.Method.ToString()); } } } } } 

También puede encontrar la coincidencia correcta guardando ManagedThreadId dentro del hilo que crea, y luego busca este mismo ID en tiempo de runtime.Threads . runtime.Threads .

Pruebas

Probado con todas las combinaciones de:

  • Visual Studio 2015 SP1
  • .NET 4.5
  • .NET 4.6.0
  • .NET 4.6.1
  • C # 5.0
  • C # 6.0

Referencias

Ver ClrMd lanza una excepción al crear el tiempo de ejecución .