从线程获取线程ID

时间:2009-11-05 09:02:17

标签: c# .net multithreading

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

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

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

11 个答案:

答案 0 :(得分:409)

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

GetCurrentThreadId返回当前线程的ID。

从.NET 2.0开始,

GetCurrentThreadId已被弃用:推荐的方法是Thread.CurrentThread.ManagedThreadId属性。

答案 1 :(得分:68)

  

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

这将是托管线程的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();

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

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

答案 2 :(得分:41)

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

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

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

答案 3 :(得分:29)

要使用操作系统ID:

AppDomain.GetCurrentThreadId()

答案 4 :(得分:21)

根据MSDN

  

操作系统ThreadId没有   与托管的固定关系   线程,因为非托管主机可以   控制之间的关系   托管和非托管线程。   具体而言,复杂的主机可以   使用CLR Hosting API来安排   许多托管线程反对同样的   操作系统线程,或移动一个   不同的托管线程   操作系统线程。

基本上,Thread对象不一定对应于操作系统线程 - 这就是为什么它没有暴露本机ID的原因。

答案 5 :(得分:12)

对于那些即将入侵的人:

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

答案 6 :(得分:10)

要查找当前线程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;
     }
}

答案 7 :(得分:5)

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

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

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

答案 8 :(得分:5)

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

答案 9 :(得分:4)

<德尔> System.Threading.Thread.CurrentThread.Name

System.Threading.Thread.CurrentThread.ManagedThreadId

答案 10 :(得分:3)

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

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

GetHashCode&#34;为需要快速检查对象相等性的算法提供此哈希码,&#34;因此它非常适合检查线程相等性 - 例如断言特定方法正在您想要调用的线程上执行。