从线程获取线程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。 ManagedThreadIdThread的成员,所以你可以从任何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线程的Threadtypes实例。 Thread封装了操作系统线程的概念,并且从当前CLR开始,与托pipe线程和操作系统线程有一对一的对应关系。 但是,这是一个实现细节,将来可能会改变。

Visual Studio显示的ID实际上是操作系统的线程ID。 这与多个回复build议的pipe理线程ID不同。

Threadtypes包括一个名为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; }