c# - with - Obteniendo el ID de hilo de un hilo
thread net core (11)
En C # al depurar hilos, por ejemplo, puede ver el ID de cada hilo.
No pude encontrar una manera de obtener ese mismo hilo, mediante programación. Ni siquiera pude obtener el ID del subproceso actual (en las propiedades de Thread.currentThread
).
Entonces, me pregunto cómo obtiene Visual Studio los identificadores de los subprocesos, y ¿hay alguna manera de obtener el identificador del subproceso con el id 2345
, por ejemplo?
En C # al depurar hilos, por ejemplo, puede ver el ID de cada hilo.
Estos serán los identificadores de los hilos gestionados. ManagedThreadId
es un miembro de Thread
por lo que puede obtener la ID de cualquier objeto Thread . Esto te dará el Thread.CurrentThread.ManagedThreadId actual:
Thread.CurrentThread.ManagedThreadId
Para obtener un subproceso de sistema operativo por su ID de hilo de sistema operativo (no ManagedThreadID) , puedes probar un poco de linq.
int unmanagedId = 2345;
ProcessThread myThread = (from ProcessThread entry in Process.GetCurrentProcess().Threads
where entry.Id == unmanagedId
select entry).First();
Parece que no hay manera de enumerar los subprocesos administrados y no hay relación entre ProcessThread y Thread, por lo que obtener un subproceso administrado por su ID es una tarea difícil.
Para obtener más detalles sobre los subprocesos administrados y no administrados, vea este artículo de MSDN .
Desde el código administrado, tiene acceso a las instancias del tipo de Thread
para cada subproceso administrado. Thread
encapsula el concepto de un subproceso del sistema operativo y, a partir del CLR actual, existe una correspondencia uno a uno con los subprocesos gestionados y los subprocesos del sistema operativo. Sin embargo, este es un detalle de implementación, que puede cambiar en el futuro.
La ID mostrada por Visual Studio es en realidad la ID del hilo del sistema operativo. Esto no es lo mismo que el ID de hilo administrado como lo sugieren varias respuestas.
El tipo de Thread
no incluye un campo de miembro de IntPtr privado llamado DONT_USE_InternalThread
, que apunta a la estructura del sistema operativo subyacente. Sin embargo, como este es realmente un detalle de implementación, no es aconsejable seguir esta OMI. Y el nombre indica que no debes confiar en esto.
El desplazamiento bajo Windows 10 es 0x022C (aplicación de x64 bits) y 0x0160 (aplicación de x32 bits):
public static int GetNativeThreadId(Thread thread)
{
var f = typeof(Thread).GetField("DONT_USE_InternalThread",
BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
var pInternalThread = (IntPtr)f.GetValue(thread);
var nativeId = Marshal.ReadInt32(pInternalThread, (IntPtr.Size == 8) ? 0x022C : 0x0160); // found by analyzing the memory
return nativeId;
}
Para aquellos a punto de hackear:
public static int GetNativeThreadId(Thread thread)
{
var f = typeof(Thread).GetField("DONT_USE_InternalThread",
BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
var pInternalThread = (IntPtr)f.GetValue(thread);
var nativeId = Marshal.ReadInt32(pInternalThread, (IntPtr.Size == 8) ? 548 : 348); // found by analyzing the memory
return nativeId;
}
Para encontrar el ID de hilo actual use - `Thread.CurrentThread.ManagedThreadId ''. Pero en este caso, es posible que necesite el ID de subproceso de win32 actual; use pInvoke para obtenerlo con esta función:
[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();
Primero deberá guardar la conexión del ID del hilo administrado y la del ID del hilo win32: use un diccionario que asigne un ID de Win32 al hilo administrado.
Luego, para encontrar un subproceso por su iteración de id sobre el subproceso del proceso utilizando Process.GetCurrentProcess (). Subprocesos y encuentre el subproceso con ese id:
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
{
var managedThread = win32ToManagedThread[thread.id];
if((managedThread.ManagedThreadId == threadId)
{
return managedThread;
}
}
Para obtener el ID del sistema operativo:
AppDomain.GetCurrentThreadId()
Puede usar Thread.GetHashCode, que devuelve la ID del hilo administrado. Si piensa en el propósito de GetHashCode, esto tiene mucho sentido: debe ser un identificador único (por ejemplo, clave en un diccionario) para el objeto (el hilo).
La fuente de referencia para la clase Thread es instructiva aquí. (Por supuesto, una implementación particular de .NET puede no estar basada en este código fuente, pero para propósitos de depuración, arriesgaré).
GetHashCode "proporciona este código hash para algoritmos que necesitan comprobaciones rápidas de la igualdad de objetos", por lo que es adecuado para verificar la igualdad de subprocesos, por ejemplo, para afirmar que un método particular se está ejecutando en el subproceso desde el que se llamó.
Puede usar el AppDomain.GetCurrentThreadId
desuso para obtener el ID del subproceso que se está ejecutando actualmente. Este método utiliza un PInvoke al método GetCurrentThreadID de la API de Win32 y devolverá el ID de subproceso de Windows.
Este método está marcado como obsoleto porque el objeto de subproceso de .NET no corresponde a un solo subproceso de Windows y, como tal, no hay una ID estable que Windows pueda devolver para un subproceso de .NET determinado.
Vea la respuesta del configurador para más razones por las que este es el caso.
Según MSDN :
Un ThreadId del sistema operativo no tiene una relación fija con un subproceso administrado, porque un host no administrado puede controlar la relación entre los subprocesos administrados y no administrados. Específicamente, un host sofisticado puede usar la API de hospedaje de CLR para programar muchos subprocesos administrados contra el mismo subproceso del sistema operativo, o para mover un subproceso administrado entre los diferentes subprocesos del sistema operativo.
Básicamente, el objeto Thread
no se corresponde necesariamente con un subproceso del sistema operativo, razón por la cual no tiene el ID nativo expuesto.
GetThreadId
devuelve el ID de un subproceso nativo dado. Hay formas de hacerlo funcionar con subprocesos administrados, estoy seguro de que todo lo que necesita encontrar es el identificador del subproceso y pasarlo a esa función.
GetCurrentThreadId
devuelve el ID del subproceso actual.
GetCurrentThreadId
ha quedado en desuso a partir de .NET 2.0: la forma recomendada es la propiedad Thread.CurrentThread.ManagedThreadId
.
System.Threading.Thread.CurrentThread.Name
System.Threading.Thread.CurrentThread.ManagedThreadId