win32 threads thread example createthread windows multithreading winapi

threads - thread c++ windows



¿Cómo establecer nombre a un hilo de Win32? (9)

¿Cómo establezco un nombre a un hilo de Win32? No encontré ninguna API de Win32 para lograr lo mismo. Básicamente quiero agregar el nombre del hilo en el archivo de registro. ¿Es TLS (Thread Local Storage) la única forma de hacerlo?



De acuerdo con la discusión con los líderes del equipo de depuración de Microsoft (vea el enlace a continuación para obtener más detalles), la API SetThreadDescription es la API que Microsoft utilizará en adelante para admitir la denominación de hilos oficialmente en código nativo. Por "oficialmente" me refiero a una API compatible con MS para la asignación de nombres a los subprocesos, a diferencia del actual truco de lanzamiento de excepciones que actualmente solo funciona mientras se está ejecutando un proceso en Visual Studio.

Esta API estuvo disponible a partir de Windows 10, versión 1607.

Sin embargo, actualmente hay muy poco soporte de herramientas, por lo que los nombres que establezca no serán visibles en los depuradores de Visual Studio o WinDbg. Sin embargo, a partir de abril de 2017, las herramientas Microsoft xperf / WPA sí lo admiten (los hilos nombrados a través de esta API harán que sus nombres se muestren correctamente en esas herramientas).

Si desea que este soporte sea mejor, como en WinDbg, Visual Studio y los archivos de volcado de fallos, vote a través de este enlace:

https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/17608120-properly-support-native-thread-naming-via-the-sett


Otra forma de hacer esto es almacenar un puntero al nombre en el campo ArbitraryUserPointer del TEB del hilo. Esto se puede escribir y leer en tiempo de ejecución.

Hay un artículo de CodeProject titulado "Depuración con el bloque de información de subprocesos" que muestra cómo hacerlo.


Puede utilizar un objeto de almacenamiento de subproceso local para almacenar el nombre. Por ejemplo,

__declspec( thread ) char threadName[32];

Luego puedes escribir y leer esto desde un hilo. Esto podría ser útil en una aplicación de registrador, donde desea imprimir el nombre del hilo para cada mensaje. Probablemente desee escribir esta variable tan pronto como comience el hilo, y también lanzar la excepción de Microsoft ( https://.com/a/10364541/364818 ) para que el depurador también sepa el nombre del hilo.




Siempre puede almacenar esta información para usted mismo en una estructura de datos adecuada. Utilice un hash o un mapa para asignar GetThreadId () a este nombre. Dado que GetThreadId () es siempre un identificador único, esto funciona bien.

Saludos!

Por supuesto, si está creando muchos subprocesos, ese hashmap se llenará lentamente y utilizará más y más memoria, por lo que algún procedimiento de limpieza probablemente también sea bueno.

Estás absolutamente en lo correcto. Cuando un hilo muere, su entrada correspondiente en el mapa debería eliminarse naturalmente.


Win32 hilos no tienen nombres. Hay una convención de Microsoft por la cual las aplicaciones generan excepciones SEH especiales que contienen un nombre de hilo. Estos depuradores pueden interceptar estas excepciones y utilizarlas para indicar el nombre del hilo. Un par de respuestas cubren eso.

Sin embargo, todo esto es manejado por el depurador. Los hilos en sí mismos son objetos sin nombre. Entonces, si quieres asociar nombres con tus hilos, tendrás que desarrollar tu propio mecanismo. Si bien puede utilizar el almacenamiento local de subprocesos que solo le permitirá obtener el nombre del código que se ejecuta en ese subproceso. Por lo tanto, un mapa global entre el ID de hilo y el nombre parecería ser el enfoque más natural y útil.


http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.90).aspx

// // Usage: SetThreadName (-1, "MainThread"); // #include <windows.h> const DWORD MS_VC_EXCEPTION=0x406D1388; #pragma pack(push,8) typedef struct tagTHREADNAME_INFO { DWORD dwType; // Must be 0x1000. LPCSTR szName; // Pointer to name (in user addr space). DWORD dwThreadID; // Thread ID (-1=caller thread). DWORD dwFlags; // Reserved for future use, must be zero. } THREADNAME_INFO; #pragma pack(pop) void SetThreadName( DWORD dwThreadID, char* threadName) { THREADNAME_INFO info; info.dwType = 0x1000; info.szName = threadName; info.dwThreadID = dwThreadID; info.dwFlags = 0; __try { RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); } __except(EXCEPTION_EXECUTE_HANDLER) { } }