Получение идентификатора потока из потока
В C# при отладке потоков, например, вы можете увидеть идентификатор каждого потока.
Я не мог найти способ получить тот же поток, программно. Я даже не мог получить идентификатор текущего потока (в свойствах Thread.currentThread).
Итак, мне интересно, как Visual Studio получает идентификаторы потоков, и есть ли способ получить дескриптор потока с id 2345, например?
11 ответов:
GetThreadIdвозвращает идентификатор данного собственного потока. Есть способы заставить его работать с управляемыми потоками, я уверен, все, что вам нужно найти, это дескриптор потока и передать его этой функции.
GetCurrentThreadIdвозвращает идентификатор текущего потока.
GetCurrentThreadIdустарел с .NET 2.0: рекомендуемый способ -Thread.CurrentThread.ManagedThreadIdсобственность.
в C# при отладке потоков, например, вы можете увидеть каждый поток ИДЕНТИФИКАТОР.
это будут идентификаторы управляемых потоков.
ManagedThreadIdявляется членомThreadтаким образом, Вы можете получить идентификатор от любого Thread
Вы можете использовать устаревший
AppDomain.GetCurrentThreadIdчтобы получить идентификатор текущего потока. Этот метод использует PInvoke для метода Win32 APIGetCurrentThreadID, и вернет идентификатор потока Windows.этот метод помечен как устаревший, поскольку объект .NET Thread не соответствует одному потоку Windows, и поэтому нет стабильного идентификатора, который может быть возвращен Windows для данного потока .NET.
см. ответ конфигуратора для получения дополнительной информации о причинах так оно и есть.
по данным 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, что указывает на базовую структуру ОС. Однако, поскольку это действительно деталь реализации, не рекомендуется преследовать эту ИМО. И название рода указывает на то, что вы не должны полагаться на это.
смещение под 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