首页 文章

从线程获取线程ID

提问于
浏览
267

例如,在调试线程的C#中,您可以看到每个线程的ID .

我无法通过编程方式找到获得相同线程的方法 . 我甚至无法获得当前线程的ID(在 Thread.currentThread 的属性中) .

所以,我想知道Visual Studio如何获取线程的ID,有没有办法获得id为 2345 的线程句柄?

11 回答

  • 9

    GetThreadId返回给定本机线程的ID . 有一些方法可以使它与托管线程一起使用,我敢肯定,您需要找到的只是线程句柄并将其传递给该函数 .

    GetCurrentThreadId返回当前线程的ID .

    GetCurrentThreadId 自.NET 2.0起已被弃用:推荐的方法是Thread.CurrentThread.ManagedThreadId属性 .

  • 389

    例如,在调试线程的C#中,您可以看到每个线程的ID .

    这将是托管线程的ID . ManagedThreadIdThread 的成员,因此您可以从任何Thread对象获取Id . 这将为您提供当前的ManagedThreadID

    Thread.CurrentThread.ManagedThreadId
    

    要通过它的OS线程ID(而不是ManagedThreadID)来获取OS线程,您可以尝试一些linq .

    int unmanagedId = 2345;
    ProcessThread myThread = (from ProcessThread entry in Process.GetCurrentProcess().Threads
       where entry.Id == unmanagedId 
       select entry).First();
    

    似乎没有办法枚举托管线程并且没有ProcessThread和Thread之间的关系,因此通过它的Id获取托管线程是一个艰难的 .

    有关托管与非托管线程的更多详细信息,请参阅this MSDN arcticle .

  • 39

    您可以使用已弃用的AppDomain.GetCurrentThreadId来获取当前正在运行的线程的ID . 此方法使用PInvoke到Win32 API方法 GetCurrentThreadID ,并将返回Windows线程ID .

    此方法被标记为已弃用,因为.NET Thread对象不对应于单个Windows线程,因此没有稳定的ID可由Windows为给定的.NET线程返回 .

    请参阅配置程序的答案,了解更多原因 .

  • 4

    要获取操作系统ID,请使用:

    AppDomain.GetCurrentThreadId()
    
  • 65

    根据MSDN

    操作系统ThreadId与托管线程没有固定关系,因为非托管主机可以控制托管和非托管线程之间的关系 . 具体而言,复杂的主机可以使用CLR Hosting API针对同一操作系统线程调度许多托管线程,或者在不同操作系统线程之间移动托管线程 .

    所以基本上, Thread 对象不一定对应于OS线程 - 这就是为什么它没有暴露本机ID的原因 .

  • 5

    对于那些即将入侵的人:

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

    要查找当前线程Id,请使用 - “Thread.CurrentThread.ManagedThreadId” . 但在这种情况下,您可能需要当前的win32线程ID - 使用pInvoke来获取此函数:

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

    首先,您需要保存托管线程ID和win32线程ID连接 - 使用将win32 id映射到托管线程的字典 .

    然后通过它的id找到一个线程使用Process.GetCurrentProcess()迭代进程的线程 . 线程并找到具有该id的线程:

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

    从托管代码中,您可以访问每个托管线程的 Thread 类型的实例 . Thread 封装了OS线程的概念,并且从当前的CLR开始,与托管线程和OS线程一一对应 . 但是,这是一个实现细节,可能在将来发生变化 .

    Visual Studio显示的ID实际上是OS线程ID . 这与多个回复建议的托管线程ID不同 .

    Thread 类型包含一个名为 DONT_USE_InternalThread 的私有IntPtr成员字段,该字段指向底层OS结构 . 但是,由于这实际上是一个实施细节,因此不宜采用这种IMO . 名称有点表明你不应该依赖于此 .

  • 12

    System.Threading.Thread.CurrentThread.Name

    System.Threading.Thread.CurrentThread.ManagedThreadId
    
  • 4

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

    您可以使用Thread.GetHashCode,它返回托管线程ID . 如果你考虑GetHashCode的目的,这很有意义 - 它需要是对象(线程)的唯一标识符(例如字典中的键) .

    reference source for the Thread class在这里很有启发性 . (当然,特定的.NET实现可能不是基于此源代码,但出于调试目的,我将 grab 机会 . )

    GetHashCode "provides this hash code for algorithms that need quick checks of object equality,"所以它非常适合检查线程相等 - 例如断言某个特定的方法正在您想要调用的线程上执行 .

相关问题