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

В С# при отладке потоков, например, вы можете увидеть каждый идентификатор потока.

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

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

Ответ 1

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

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

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

Ответ 2

В С# при отладке потоков, например, вы можете видеть каждый поток ID.

Это будут идентификаторы управляемых потоков. ManagedThreadId является членом Thread, поэтому вы можете получить идентификатор из любого объекта 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, поэтому получение управляемого потока с помощью Id Id является жестким.

Подробнее о Managed vs Unmanaged threading см. этот файл MSDN.

Ответ 3

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

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

См. ответ конфигуратора по другим причинам, почему это так.

Ответ 4

Чтобы использовать идентификатор ОС:

AppDomain.GetCurrentThreadId()

Ответ 5

Согласно MSDN:

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

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

Ответ 6

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

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

Ответ 7

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

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

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

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

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

Ответ 8

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

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

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

Ответ 9

System.Threading.Thread.CurrentThread.Nameдел >

System.Threading.Thread.CurrentThread.ManagedThreadId

Ответ 10

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

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

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

Ответ 11

Смещение по 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;
}