web-dev-qa-db-fra.com

Obtenir l'identifiant d'un thread

En C # lors du débogage de threads par exemple, vous pouvez voir l'ID de chaque thread.

Je ne pouvais pas trouver un moyen d'obtenir ce même fil, par programme. Je ne pouvais même pas obtenir l'ID du thread actuel (dans les propriétés du Thread.currentThread).

Je me demande donc comment Visual Studio obtient les ID des threads. Y a-t-il un moyen d’obtenir le handle du thread avec id 2345, par exemple?

298
LolaRun

GetThreadId renvoie l'ID d'un thread natif donné. Il existe des moyens de le faire fonctionner avec des threads gérés, j'en suis sûr, tout ce que vous avez besoin de trouver, c'est le handle du thread et le transmettre à cette fonction.

GetCurrentThreadId renvoie l'ID du thread actuel.

GetCurrentThreadId est obsolète depuis .NET 2.0: la méthode recommandée est la propriété Thread.CurrentThread.ManagedThreadId .

416
Blindy

En C # lors du débogage de threads par exemple, vous pouvez voir l'ID de chaque thread.

Ce seront les ID des threads gérés. ManagedThreadId est un membre de Thread afin que vous puissiez obtenir l'ID de n'importe quel objet Thread . Cela vous donnera le courant ManagedThreadID :

Thread.CurrentThread.ManagedThreadId

Pour obtenir un thread OS par son ID (pas ManagedThreadID) , vous pouvez essayer un peu de linq.

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

Il semble qu'il n'y ait aucun moyen d'énumérer les threads gérés et aucune relation entre ProcessThread et Thread, il est donc difficile d'obtenir un thread géré par son ID.

Pour plus de détails sur les threads gérés et non gérés, voir this MSDN arcticle .

74
badbod99

Vous pouvez utiliser le paramètre obsolète AppDomain.GetCurrentThreadId pour obtenir l'ID du thread en cours d'exécution. Cette méthode utilise un PInvoke sur la méthode de l'API Win32 GetCurrentThreadID et renvoie l'ID de thread Windows.

Cette méthode est marquée comme obsolète car l'objet .NET Thread ne correspond pas à un seul thread Windows et, en tant que tel, il n'existe aucun ID stable pouvant être renvoyé par Windows pour un thread .NET donné.

Voir la réponse du configurateur pour plus de raisons pour lesquelles c'est le cas.

42
Paul Turner

Pour obtenir l'ID du système d'exploitation, utilisez:

AppDomain.GetCurrentThreadId()
30
Mark Byers

Selon MSDN :

Un ThreadId de système d'exploitation n'a pas de relation fixe avec un thread géré, car un hôte non géré peut contrôler la relation entre les threads gérés et non gérés. Plus précisément, un hôte sophistiqué peut utiliser l'API d'hébergement CLR pour planifier plusieurs threads gérés avec le même thread du système d'exploitation ou pour déplacer un thread géré entre différents threads du système d'exploitation.

Donc, fondamentalement, l’objet Thread ne correspond pas nécessairement à un thread d’exploitation - c’est pourquoi il n’a pas l’ID natif exposé.

21
configurator

Pour ceux sur le point de pirater:

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

Pour trouver l'ID de thread actuel, utilisez - Thread.CurrentThread.ManagedThreadId. Mais dans ce cas, vous aurez peut-être besoin de l'id du thread Win32 actuel - utilisez pInvoke pour l'obtenir avec cette fonction:

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

Vous devez d’abord enregistrer l’identité du thread géré et la connexion de l’identité du thread Win32 - utilisez un dictionnaire qui mappe un identifiant Win32 sur le thread géré.

Ensuite, pour rechercher un thread par son id, parcourez le thread du processus à l'aide de Process.GetCurrentProcess (). Threads et recherchez le thread avec cet identifiant:

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

Le décalage sous Windows 10 est 0x022C (application x64 bits) et 0x0160 (application 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;
}
9
Handball Reporter

System.Threading.Thread.CurrentThread.Name

System.Threading.Thread.CurrentThread.ManagedThreadId
5
Manu

Depuis le code managé, vous avez accès aux instances du type Thread pour chaque thread géré. Thread encapsule le concept d'un thread de système d'exploitation. Depuis le CLR actuel, il existe une correspondance un à un avec les threads gérés et les threads de système d'exploitation. Cependant, il s’agit d’un détail de la mise en œuvre, qui pourrait changer dans le futur.

L'ID affiché par Visual Studio est en réalité l'ID de thread du système d'exploitation. Ceci est pas identique à l'ID de thread géré, comme suggéré par plusieurs réponses.

Le type Thread inclut un champ de membre privé IntPtr appelé DONT_USE_InternalThread, qui pointe vers la structure de système d'exploitation sous-jacente. Cependant, comme il s’agit vraiment d’un détail de mise en œuvre, il n’est pas conseillé de poursuivre cette OMI. Et le nom indique en quelque sorte que vous ne devriez pas compter sur cela.

5
Brian Rasmussen

Vous pouvez utiliser Thread.GetHashCode, qui renvoie l'ID de thread géré. Si vous pensez au but de GetHashCode, cela a du sens: il doit s'agir d'un identifiant unique (par exemple, la clé dans un dictionnaire) pour l'objet (le thread).

Le source de référence pour la classe Thread est instructif ici. (Certes, une implémentation .NET particulière peut ne pas être basée sur ce code source, mais je vais tenter ma chance à des fins de débogage.)

GetHashCode "fournit ce code de hachage pour les algorithmes nécessitant une vérification rapide de l'égalité des objets", il est donc bien adapté à la vérification de l'égalité des threads, par exemple pour affirmer qu'une méthode particulière est en cours d'exécution sur le thread que vous utilisez. je voulais l'appeler de.

3
yoyo