Ottenere l’ID del thread da un thread

Ad esempio, in C # durante il debug dei thread, puoi vedere l’ID di ciascun thread.

Non sono riuscito a trovare un modo per ottenere lo stesso thread, a livello di codice. Non riuscivo nemmeno a ottenere l’ID del thread corrente (nelle proprietà di Thread.currentThread ).

Quindi, mi chiedo come fa Visual Studio ad ottenere gli ID dei thread, e c’è un modo per ottenere l’handle del thread con id 2345 , per esempio?

GetThreadId restituisce l’ID di un determinato thread nativo. Ci sono modi per farlo funzionare con thread gestiti, ne sono sicuro, tutto quello che devi trovare è l’handle del thread e passarlo a quella funzione.

GetCurrentThreadId restituisce l’ID del thread corrente.

GetCurrentThreadId è stato deprecato da .NET 2.0: il modo consigliato è la proprietà Thread.CurrentThread.ManagedThreadId .

Ad esempio, in C # durante il debug dei thread, puoi vedere l’ID di ciascun thread.

Questo sarà l’ID dei thread gestiti. ManagedThreadId è un membro di Thread modo da poter ottenere l’Id da qualsiasi object Thread . Questo ti darà l’attuale ManagedThreadID :

 Thread.CurrentThread.ManagedThreadId 

Per ottenere un thread del sistema operativo tramite l’ID del thread del sistema operativo (non ManagedThreadID) , è ansible provare un po ‘di linq.

 int unmanagedId = 2345; ProcessThread myThread = (from ProcessThread entry in Process.GetCurrentProcess().Threads where entry.Id == unmanagedId select entry).First(); 

Sembra che non vi sia alcun modo per enumerare i thread gestiti e nessuna relazione tra ProcessThread e Thread, quindi ottenere un thread gestito in base all’ID è difficile.

Per ulteriori dettagli sui thread gestiti e non gestiti vedere questo articolo MSDN .

È ansible utilizzare AppDomain.GetCurrentThreadId obsoleto per ottenere l’ID del thread attualmente in esecuzione. Questo metodo utilizza PInvoke per il metodo API Win32 GetCurrentThreadID e restituirà l’ID del thread di Windows.

Questo metodo è contrassegnato come deprecato perché l’object Thread .NET non corrisponde a un singolo thread di Windows e pertanto non esiste alcun ID stabile che possa essere restituito da Windows per un determinato thread .NET.

Vedi la risposta del configuratore per più motivi per cui questo è il caso.

Per ottenere l’ID del sistema operativo, utilizzare:

 AppDomain.GetCurrentThreadId() 

Secondo MSDN :

Un ThreadId del sistema operativo non ha una relazione fissa con un thread gestito, poiché un host non gestito può controllare la relazione tra thread gestiti e non gestiti. In particolare, un host sofisticato può utilizzare l’API di hosting CLR per pianificare molti thread gestiti sullo stesso thread del sistema operativo o per spostare un thread gestito tra diversi thread del sistema operativo.

Quindi, in pratica, l’object Thread non corrisponde necessariamente a un thread del sistema operativo, motivo per cui non ha l’ID nativo esposto.

Per chi sta per hackerare:

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

Per trovare l’ID del thread corrente utilizzare – `Thread.CurrentThread.ManagedThreadId ‘. Ma in questo caso potrebbe essere necessario l’id corrente del thread win32: utilizzare pInvoke per ottenerlo con questa funzione:

 [DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] public static extern Int32 GetCurrentWin32ThreadId(); 

Innanzitutto è necessario salvare l’ID del thread gestito e la connessione dell’ID thread win32: utilizzare un dizionario che associa un ID win32 al thread gestito.

Quindi per trovare un thread in base all’ID iterato sul thread del processo utilizzando Process.GetCurrentProcess (). Thread e trovare il thread con quell’id:

 foreach (ProcessThread thread in Process.GetCurrentProcess().Threads) { var managedThread = win32ToManagedThread[thread.id]; if((managedThread.ManagedThreadId == threadId) { return managedThread; } } 

Dal codice gestito hai accesso alle istanze del tipo Thread per ogni thread gestito. Thread incapsula il concetto di un thread del sistema operativo e dal CLR corrente esiste una corrispondenza uno a uno con thread gestiti e thread del sistema operativo. Tuttavia, questo è un dettaglio di implementazione, che potrebbe cambiare in futuro.

L’ID visualizzato da Visual Studio è in realtà l’ID del thread del sistema operativo. Questo non è lo stesso dell’ID thread gestito come suggerito da diverse risposte.

Il tipo di Thread include un campo membro IntPtr privato chiamato DONT_USE_InternalThread , che punta alla struttura del sistema operativo sottostante. Tuttavia, poiché questo è davvero un dettaglio di implementazione, non è consigliabile seguire questo IMO. E il nome indica che non dovresti fare affidamento su questo.

System.Threading.Thread.CurrentThread.Name

 System.Threading.Thread.CurrentThread.ManagedThreadId 

L’offset in Windows 10 è 0x022C (x64-bit-Application) e 0x0160 (x32-bit-Application):

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

È ansible utilizzare Thread.GetHashCode, che restituisce l’ID del thread gestito. Se si pensa allo scopo di GetHashCode, questo è logico: deve essere un identificativo univoco (ad esempio, la chiave in un dizionario) per l’object (il thread).

La fonte di riferimento per la class Thread è istruttiva qui. (Certo, una particolare implementazione .NET potrebbe non essere basata su questo codice sorgente, ma per scopi di debug proverò le mie possibilità.)

GetHashCode “fornisce questo codice hash per algoritmi che richiedono controlli rapidi di uguaglianza di oggetti”, quindi è adatto per controllare l’uguaglianza dei thread, ad esempio per asserire che un determinato metodo è in esecuzione sul thread da cui si desidera che venga chiamato.