Answers:
GetThreadId
返回给定本机线程的ID。有很多方法可以使其与托管线程一起使用,我敢肯定,您需要找到的只是线程句柄并将其传递给该函数。
GetCurrentThreadId
返回当前线程的ID。
GetCurrentThreadId
从.NET 2.0开始不推荐使用:推荐的方式是Thread.CurrentThread.ManagedThreadId
属性。
System.Threading.Thread.CurrentThread.ManagedThreadId
至少在in中使用时无效SetWindowsHookEx
。相反,我们必须从本地win32函数获取线程ID GetCurrentThreadId()
。
例如,在C#中调试线程时,您可以看到每个线程的ID。
这将是托管线程的ID。 ManagedThreadId
是的成员,Thread
因此您可以从任何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获得托管线程是一项艰巨的任务。
有关托管线程与非托管线程的更多详细信息,请参见此MSDN arcticle。
您可以使用不赞成使用的方法AppDomain.GetCurrentThreadId
来获取当前正在运行的线程的ID。此方法对Win32 API方法使用PInvoke GetCurrentThreadID
,并将返回Windows线程ID。
此方法被标记为已弃用,因为.NET Thread对象不对应于单个Windows线程,因此,对于给定的.NET线程,没有Windows可以返回的稳定ID。
有关更多原因,请参阅配置程序的答案。
要获取OS ID,请使用:
AppDomain.GetCurrentThreadId()
AppDomain.GetCurrentThreadId()
已过时:AppDomain.GetCurrentThreadId
已弃用,因为当托管线程在上运行时,它不提供稳定的ID fibers (aka lightweight threads)
。要获取托管线程的稳定标识符,请使用上的ManagedThreadId
属性Thread
。用法:Thread.CurrentThread.ManagedThreadId
根据MSDN:
操作系统ThreadId与托管线程没有固定的关系,因为非托管主机可以控制托管线程和非托管线程之间的关系。具体来说,复杂的主机可以使用CLR Hosting API来针对同一操作系统线程调度许多托管线程,或者在不同的操作系统线程之间移动托管线程。
因此,基本上,该Thread
对象不一定与OS线程相对应-这就是为什么它没有公开本机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;
}
要查找当前线程ID,请使用-Thread.CurrentThread.ManagedThreadId。但是在这种情况下,您可能需要当前的win32线程ID-使用pInvoke可以通过以下功能获取它:
[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();
首先,您需要保存托管线程ID和Win32线程ID连接-使用将Win32 ID映射到托管线程的字典。
然后,使用Process.GetCurrentProcess()。Threads通过其ID来查找线程,以对该进程的线程进行迭代,并找到具有该ID的线程:
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
{
var managedThread = win32ToManagedThread[thread.id];
if((managedThread.ManagedThreadId == threadId)
{
return managedThread;
}
}
ProcessThread
对象的集合,这与对象集合相同(也不继承)Thread
:(thread as Thread)
将返回空引用。
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;
}
从托管代码中,您可以访问Thread
每个托管线程的类型的实例。Thread
封装了OS线程的概念,从当前的CLR开始,托管线程和OS线程是一一对应的。但是,这是一个实现细节,将来可能会更改。
Visual Studio显示的ID实际上是操作系统线程ID。这是不一样的托管线程ID几种答复的建议。
该Thread
类型确实包含一个名为的私有IntPtr成员字段DONT_USE_InternalThread
,该成员字段指向基础OS结构。但是,由于这实际上是一个实现细节,因此不建议执行此IMO。而且名称名称表明您不应该依赖于此。
您可以使用Thread.GetHashCode,它返回托管线程ID。如果您考虑GetHashCode的目的,那么这很有意义-它必须是对象(线程)的唯一标识符(例如,字典中的键)。
Thread类的参考源在这里具有指导意义。(当然,特定的.NET实现可能不基于此源代码,但是出于调试目的,我会抓住机会。)
GetHashCode “为需要快速检查对象相等性的算法提供了此哈希码,”因此它非常适合检查线程是否相等-例如断言某个特定方法正在您要从其调用的线程上执行。