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



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



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



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

1143   11  

11 ответов:

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

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

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

в C# при отладке потоков, например, вы можете увидеть каждый поток ИДЕНТИФИКАТОР.

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

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

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

см. ответ конфигуратора для получения дополнительной информации о причинах так оно и есть.

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

AppDomain.GetCurrentThreadId()

по данным MSDN:

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

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

для тех, кто собирается рубить:

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

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

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

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

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

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

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

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

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

System.Threading.Thread.CurrentThread.Name

System.Threading.Thread.CurrentThread.ManagedThreadId

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

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

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

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

Comments

    Ничего не найдено.