从线程获取线程ID
在C#中,当debugging线程时,你可以看到每个线程的ID。
我无法find一种方式来获得相同的线程,以编程方式。 我什至不能得到当前线程的ID(在Thread.currentThread
属性中)。
所以,我想知道Visual Studio如何获得线程的ID,并有一种方法来获得与ID 2345
线程的句柄,例如?
GetThreadId
返回给定本地线程的ID。 有一些方法可以使它与托pipe线程一起工作,我相信,您只需要find线程句柄并将其传递给该函数即可。
GetCurrentThreadId
返回当前线程的ID。
从.NET 2.0开始, GetCurrentThreadId
已被弃用:推荐的方法是Thread.CurrentThread.ManagedThreadId
属性。
在C#中,当debugging线程时,你可以看到每个线程的ID。
这将是托pipe线程的ID。 ManagedThreadId
是Thread
的成员,所以你可以从任何Thread对象获取Id。 这将使您获得当前的ManagedThreadID :
Thread.CurrentThread.ManagedThreadId
要通过操作系统线程ID (而不是ManagedThreadID)获得操作系统线程,可以尝试一下linq。
int unmanagedId = 2345; ProcessThread myThread = (from ProcessThread entry in Process.GetCurrentProcess().Threads where entry.Id == unmanagedId select entry).First();
似乎没有办法枚举托pipe线程和ProcessThread和线程之间没有关系,所以通过它的Id获得托pipe线程是一个艰难的。
有关托pipevs非托pipe线程的更多详细信息,请参阅此MSDN arcticle 。
您可以使用弃用的AppDomain.GetCurrentThreadId
来获取当前正在运行的线程的ID。 此方法使用一个PInvoke到Win32 API方法GetCurrentThreadID
,并将返回Windows线程ID。
此方法被标记为已弃用,因为.NET线程对象不对应于单个Windows线程,因此Windows没有给定的.NET线程返回稳定的ID。
更多的理由来看configuration的答案。
要获得操作系统ID使用:
AppDomain.GetCurrentThreadId()
根据MSDN :
操作系统ThreadId与托pipe线程没有固定关系,因为非托pipe主机可以控制托pipe线程和非托pipe线程之间的关系。 具体而言,复杂的主机可以使用CLR Hosting API来针对相同的操作系统线程调度多个托pipe线程,或者在不同的操作系统线程之间移动托pipe线程。
所以基本上, Thread
对象不一定对应于一个操作系统线程 – 这就是为什么它没有暴露的本机ID。
对于那些即将破解:
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; }
find当前线程Id使用 – “Thread.CurrentThread.ManagedThreadId”。 但在这种情况下,你可能需要当前的win32线程ID – 使用pInvoke来获得它的function:
[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)] public static extern Int32 GetCurrentWin32ThreadId();
首先,您需要保存托pipe线程ID和win32线程ID连接 – 使用将win32 id映射到托pipe线程的字典。
然后通过它的idfind一个线程迭代进程的线程使用Process.GetCurrentProcess()。线程和find与该ID的线程:
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads) { var managedThread = win32ToManagedThread[thread.id]; if((managedThread.ManagedThreadId == threadId) { return managedThread; } }
从托pipe代码中,您可以访问每个托pipe线程的Thread
types实例。 Thread
封装了操作系统线程的概念,并且从当前CLR开始,与托pipe线程和操作系统线程有一对一的对应关系。 但是,这是一个实现细节,将来可能会改变。
Visual Studio显示的ID实际上是操作系统的线程ID。 这与多个回复build议的pipe理线程ID不同。
Thread
types包括一个名为DONT_USE_InternalThread
的私有IntPtr成员字段,它指向底层的OS结构。 但是,由于这实际上是一个实施细节,所以追求这个IMO是不可取的。 这个名字表明你不应该依赖这个。
System.Threading.Thread.CurrentThread.Name
System.Threading.Thread.CurrentThread.ManagedThreadId
您可以使用Thread.GetHashCode,它返回托pipe的线程ID。 如果你考虑GetHashCode的目的,这是很有意义的 – 它必须是对象(线程)的唯一标识符(例如键字)。
Thread类的参考源在这里很有指导意义。 (当然,一个特定的.NET实现可能不是基于这个源代码,但为了debugging目的,我将抓住机会。)
GetHashCode “为需要快速检查对象相等性的algorithm提供了这个哈希码”,所以它非常适合检查线程的相等性 – 例如断言一个特定的方法正在你想要调用的线程上执行。
Windows 10下的偏移量是0x022C(x64位应用程序)和0x0160(x32位应用程序):
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; }