una traves todos subprocesos subproceso seguras requiere realizar que para otro metodo los llamó llamar llamadas interfaz función framework formularios evaluación ejecuten diferente desde controles control como checkforillegalcrossthreadcalls aplicación aplanó acceder c# .net

traves - metodo invoke c#



¿Cómo hago un volcado de subprocesos en.NET?(a la descarga de subprocesos JVM) (6)

No he encontrado forma de descargar la pila en todos los hilos en .NET. Ni una señal para enviar al proceso ni acceso programático a todos los hilos. Solo puedo acceder al hilo actual a través de Thread.CurrentThread.

¿Algún truco?


Escribí un volcador para un proyecto en el que trabajé en el pasado:

void CrashHandler::WriteThreadInfo(StringWriter* sw, ArrayList* threads, String* type) { sw->WriteLine(type); IEnumerator* ie = threads->GetEnumerator(); while(ie->MoveNext()) { botNETThread* bnt = static_cast<botNETThread*>(ie->Current); if(!bnt->IsAlive) continue; sw->WriteLine(String::Concat(S"ORIGIN ASSEMBLY: ", bnt->Assembly->FullName)); sw->WriteLine(String::Concat(S"THREAD NAME: ", (bnt->Name && bnt->Name->Length)?bnt->Name:S"Unnamed thread")); sw->Write(GetStackTrace(bnt->_thread)); sw->WriteLine(); sw->WriteLine(); } } String* CrashHandler::GetStackTrace(Thread* t) { System::Diagnostics::StackTrace __gc * trace1 = __gc new System::Diagnostics::StackTrace(t, true); System::String __gc * text1 = System::Environment::NewLine; System::Text::StringBuilder __gc * builder1 = __gc new System::Text::StringBuilder(255); for (System::Int32 num1 = 0; (num1 < trace1->FrameCount); num1++) { System::Diagnostics::StackFrame __gc * frame1 = trace1->GetFrame(num1); builder1->Append(S" at "); System::Reflection::MethodBase __gc * base1 = frame1->GetMethod(); System::Type __gc * type1 = base1->DeclaringType; if (type1 != 0) { System::String __gc * text2 = type1->Namespace; if (text2 != 0) { builder1->Append(text2); if (builder1 != 0) { builder1->Append(S"."); } } builder1->Append(type1->Name); builder1->Append(S"."); } builder1->Append(base1->Name); builder1->Append(S"("); System::Reflection::ParameterInfo __gc * infoArray1 __gc [] = base1->GetParameters(); for (System::Int32 num2 = 0; (num2 < infoArray1->Length); num2++) { System::String __gc * text3 = S"<UnknownType>"; if (infoArray1[num2]->ParameterType != 0) { text3 = infoArray1[num2]->ParameterType->Name; } builder1->Append(System::String::Concat(((num2 != 0) ? S", " : S""), text3, S" ", infoArray1[num2]->Name)); } builder1->Append(S")"); if (frame1->GetILOffset() != -1) { System::String __gc * text4 = 0; try { text4 = frame1->GetFileName(); } catch (System::Security::SecurityException*) { } if (text4 != 0) { builder1->Append(System::String::Concat(S" in ", text4, S":line ", frame1->GetFileLineNumber().ToString())); } } if (num1 != (trace1->FrameCount - 1)) { builder1->Append(text1); } } return builder1->ToString(); }

Puede usar Process.GetCurrentProcess (). Threads para obtener hilos

Y sé que espabé Managed C ++, pero es bastante fácil de seguir. Tomo una lista de hilos porque para mi propósito había catagorizado mis hilos. Y sí, utilicé código de marco de pila previamente escrito, ya que era nuevo en MC ++ en ese momento :)

El archivo completo está aquí . Esto fue para un motor de programación de Diablo II que escribí hace un tiempo.


Hay una variedad de prácticas clases en el Sistema. Diagnósticos que pueden ayudarlo a depurar y recopilar información de seguimiento, es decir, StackTrace.

Hay una clase de proceso insegura que se puede usar para obtener el número de subprocesos de ejecución pero muy pocos detalles. Use el siguiente fragmento:

Using System.Diagnostics; var threads = Process.GetCurrentProcess().Threads;

Bien, después de mirar un poco más, parece que la forma más fácil de capturar todas las pilas actuales es a través de un mini volcado y una herramienta como SOS o si está ejecutando vista esto .

Buena suerte.


Solo para salvar a alguien más, la molestia aquí es el puerto de arriba para c #:

static void WriteThreadInfo(StringBuilder sw, IEnumerable<Thread> threads) { foreach(Thread thread in threads) { if(!thread.IsAlive) continue; sw.Append(String.Concat("THREAD NAME: ", thread.Name)); sw.Append(GetStackTrace(thread)); sw.AppendLine(); sw.AppendLine(); } } static String GetStackTrace(Thread t) { t.Suspend(); var trace1 = new StackTrace(t, true); t.Resume(); String text1 = System.Environment.NewLine; var builder1 = new StringBuilder(255); for (Int32 num1 = 0; (num1 < trace1.FrameCount); num1++) { StackFrame frame1 = trace1.GetFrame(num1); builder1.Append(" at "); System.Reflection.MethodBase base1 = frame1.GetMethod(); Type type1 = base1.DeclaringType; if (type1 != null) { String text2 = type1.Namespace; if (text2 != null) { builder1.Append(text2); builder1.Append("."); } builder1.Append(type1.Name); builder1.Append("."); } builder1.Append(base1.Name); builder1.Append("("); System.Reflection.ParameterInfo [] infoArray1 = base1.GetParameters(); for (Int32 num2 = 0; (num2 < infoArray1.Length); num2++) { String text3 = "<UnknownType>"; if (infoArray1[num2].ParameterType != null) { text3 = infoArray1[num2].ParameterType.Name; } builder1.Append(String.Concat(((num2 != 0) ? ", " : ""), text3, " ", infoArray1[num2].Name)); } builder1.Append(")"); if (frame1.GetILOffset() != -1) { String text4 = null; try { text4 = frame1.GetFileName(); } catch (System.Security.SecurityException) { } if (text4 != null) { builder1.Append(String.Concat(" in ", text4, ":line ", frame1.GetFileLineNumber().ToString())); } } if (num1 != (trace1.FrameCount - 1)) { builder1.Append(text1); } } return builder1.ToString(); }

No he encontrado una manera de obtener una lista de todos los hilos gestionados en C # (solo ProcessThreads), por lo que parece que necesitas mantener la lista de hilos que te interesan.

También descubrí que no podía llamar a Stacktrace (t, true) nuevo en un hilo en ejecución, por lo que agregué pausa y currículos. Obviamente, deberá considerar si esto podría causar problemas si fuera a enhebrar su aplicación de producción .

Por cierto, hemos puesto esta llamada en nuestra interfaz de aplicaciones wcf rest para que sea fácil de hacer.


Si intenta obtener un volcado de pila mientras el proceso ya está en ejecución (a la jstack), hay dos métodos como se describe aquí :

Usando Managed Stack Explorer

Hay una herramienta poco conocida pero efectiva llamada Managed Stack Explorer . Aunque cuenta con una GUI básica, puede ser un equivalente .NET de jstack si se agrega a la ruta; entonces solo es cuestión de tipear:

mse /s /p <pid>

Usando windbg

  1. Descargue e instale las herramientas de depuración apropiadas para la versión de Windows para su arquitectura (x86 / x64 / Itanium)
  2. Si necesita información sobre las llamadas a la función de Windows (por ejemplo, desea rastrear las llamadas al kernel), descargue e instale los símbolos apropiados. Esto no es estrictamente necesario si solo quieres un volcado de hilo de tu propio código.
  3. Si necesita números de línea u otra información detallada, asegúrese de colocar los archivos PDB de sus ensambles donde el depurador pueda encontrarlos (normalmente los coloca junto a sus ensamblajes reales).
  4. Inicio-> Programas-> Herramientas de depuración para Windows [x64] -> windbg
  5. Adjunte el depurador a su proceso en ejecución usando el menú
  6. Cargue la extensión SOS con ".loadby sos mscorwks" para .NET 2.0 (".load sos" para .NET 1.0 / 1.1)
  7. Toma un volcado de hilo usando "! Eestack"
  8. Separar usando ".detach"

Me pareció necesario tomar un volcado de producción de hilo y esto funcionó para mí. Espero eso ayude :-)


La mejor herramienta que he visto en este momento para generar volcados de subprocesos para .NET CLR es DebugDiag. Esta herramienta generará un informe muy detallado (utilizando el analizador Crash / Hang) de los hilos CLR activos junto con las recomendaciones.

Recomiendo revisar el siguiente tutorial .NET DebugDiag, ya que muestra el proceso de análisis en acción después de un problema de producción. Los pasos son los siguientes:

  • Crea un archivo de volcado de tu proceso w3wp afectado
  • Inicie la herramienta de diagnóstico de depuración, seleccione y ejecute los analizadores Crash / Hang.
  • Abra y analice la descripción general del análisis del informe.
  • Finalmente, revise el resumen del Tema bloqueado y realice un análisis de inmersión más profundo.

Si necesita hacer esto programáticamente (tal vez desee volcados automáticos durante su proceso de CI), puede usar la información de esta respuesta a una pregunta diferente.

Básicamente, conéctelo a su propio proceso usando CLR MD :

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) { IList<ClrStackFrame> stackFrames = thread.StackTrace; PrintStackTrace(stackFrames); } }

Aquí PrintStackTrace se deja como un ejercicio para el lector.