it-swarm.com.ru

Получение идентификатора потока из потока

Например, в C # при отладке потоков вы можете видеть идентификатор каждого потока.

Я не мог найти способ получить ту же нить программным способом. Я даже не смог получить идентификатор текущего потока (в свойствах Thread.currentThread).

Итак, мне интересно, как Visual Studio получает идентификаторы потоков, и есть ли способ, например, получить дескриптор потока с идентификатором 2345?

293
LolaRun

GetThreadId возвращает идентификатор заданного собственного потока. Есть способы заставить его работать с управляемыми потоками, я уверен, все, что вам нужно найти, - это дескриптор потока и передать его этой функции.

GetCurrentThreadId возвращает идентификатор текущего потока.

Начиная с .NET 2.0, GetCurrentThreadId устарело: рекомендуемый способ - это свойство Thread.CurrentThread.ManagedThreadId .

411
Blindy

Например, в C # при отладке потоков вы можете видеть идентификатор каждого потока.

Это будут идентификаторы управляемых потоков. ManagedThreadId является членом Thread, поэтому вы можете получить Id из любого Thread объекта. Это даст вам текущий ManagedThreadID :

Thread.CurrentThread.ManagedThreadId

Чтобы получить поток ОС по его идентификатору потока ОС (не ManagedThreadID) , вы можете попробовать немного linq.

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

Кажется, что нет никакого способа перечислить управляемые потоки и нет никакой связи между ProcessThread и Thread, поэтому получить управляемый поток по его идентификатору сложно.

Дополнительные сведения об управляемой и неуправляемой многопоточности см. В разделе этот раздел MSDN .

70
badbod99

Вы можете использовать устаревший AppDomain.GetCurrentThreadId , чтобы получить идентификатор текущего запущенного потока. Этот метод использует PInvoke для метода Win32 API GetCurrentThreadID и возвращает идентификатор потока Windows.

Этот метод помечен как устаревший, поскольку объект .NET Thread не соответствует ни одному потоку Windows, и поэтому отсутствует стабильный идентификатор, который может быть возвращен Windows для данного потока .NET.

Посмотрите ответ конфигуратора для большего количества причин, почему это так.

41
Paul Turner

Для получения идентификатора ОС используйте:

AppDomain.GetCurrentThreadId()
29
Mark Byers

Согласно MSDN :

ThreadId операционной системы не имеет фиксированной связи с управляемым потоком, потому что неуправляемый хост может контролировать отношения между управляемыми и неуправляемыми потоками. В частности, сложный хост может использовать API-интерфейс хостинга CLR для планирования многих управляемых потоков в одном потоке операционной системы или для перемещения управляемого потока между различными потоками операционной системы.

Таким образом, по сути, объект Thread не обязательно соответствует потоку ОС - вот почему у него нет собственного идентификатора.

21
configurator

Для тех, кто собирается взломать:

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

Чтобы найти текущий идентификатор потока, используйте - Thread.CurrentThread.ManagedThreadId. Но в этом случае вам может понадобиться текущий идентификатор потока win32 - используйте pInvoke, чтобы получить его с помощью этой функции:

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

Сначала вам нужно сохранить соединение управляемого потока и идентификатора потока win32 - используйте словарь, который отображает идентификатор win32 в управляемый поток.

Затем, чтобы найти поток по его идентификатору, выполните итерацию по потоку процесса с помощью Process.GetCurrentProcess (). Threads и найдите поток с этим идентификатором:

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

Смещение под Windows 10 составляет 0x022C (x64-bit-Application) и 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;
}
7
Handball Reporter

Из управляемого кода у вас есть доступ к экземплярам типа Thread для каждого управляемого потока. Thread инкапсулирует концепцию потока ОС, и в текущем CLR существует однозначное соответствие с управляемыми потоками и потоками ОС. Однако это деталь реализации, которая может измениться в будущем.

ID, отображаемый в Visual Studio, фактически является идентификатором потока ОС. Это не то же самое, что и идентификатор управляемого потока, как предлагается в нескольких ответах.

Тип Thread включает частное поле члена IntPtr с именем DONT_USE_InternalThread, которое указывает на базовую структуру ОС. Тем не менее, поскольку это действительно детали реализации, не рекомендуется использовать эту IMO. И название указывает на то, что вы не должны полагаться на это.

5
Brian Rasmussen

System.Threading.Thread.CurrentThread.Name

System.Threading.Thread.CurrentThread.ManagedThreadId
4
Manu

Вы можете использовать Thread.GetHashCode, который возвращает идентификатор управляемого потока. Если вы думаете о назначении GetHashCode, это имеет смысл - это должен быть уникальный идентификатор (например, ключ в словаре) для объекта (потока).

справочный источник для класса Thread здесь показателен. (Конечно, конкретная реализация .NET может не основываться на этом исходном коде, но в целях отладки я рискну.)

GetHashCode "предоставляет этот хэш-код для алгоритмов, которые требуют быстрой проверки равенства объектов", поэтому он хорошо подходит для проверки равенства потоков - например, чтобы утверждать, что конкретный метод выполняется в потоке, который вы хотел это позвонил с.

3
yoyo