如何以CLR“友好”的方式获取_real_线程ID?

作为练习,我正在编写一些代码来显示进程内的O / S进程和O / S线程(如Sysinternals进程资源管理器那样)。

我发现.net的ManagedThreadId(s)不是O / S线程ID。 经过一些阅读后,我遇到了AppDomain.GetCurrentThreadId()。 不幸的是,该function被标记为“过时”(这可能意味着将来“不可用”)。 我找到的一个解决方案是使用InteropServices直接调用Win32 GetCurrentThreadId。 我很好,但是,它与.net哲学背道而驰。

我的问题是:是否有一种CLR“友好”的方式来获取当前线程的真实ID?

作为参考,这里有一段代码,显示了我到目前为止所尝试的内容。 // 1和// 2显示正确的线程ID,// 3和// 4尝试以CLR友好的方式获取相同的信息(但它们不起作用。)

谢谢您的帮助,

约翰。

[DllImport("kernel32.dll")] static extern int GetCurrentThreadId(); static void Main(string[] args) { // AppDomain.GetCurrentThreadId() is "obsolete" int ThreadId1 = AppDomain.GetCurrentThreadId(); // 1 // not the ".net" way of doing things int ThreadId2 = GetCurrentThreadId(); // 2 // "no joy" attempts to get the same results I got above int ThreadId3 = Process.GetCurrentProcess().Threads[0].Id; // 3 int ThreadId4 = Thread.CurrentThread.ManagedThreadId; // 4 Console.WriteLine("ThreadId1: {0}, ThreadId2: {1}, ThreadId3: {2}, " + "ThreadId4: {3}", ThreadId1, ThreadId2, ThreadId3, ThreadId4); } 

PInvoking到GetCurrentThreadId是您最好的选择,并将为您提供正确的信息。

但是我必须警告你,CLR没有提供这些信息的理由很充分:对于托管代码来说,它几乎是一个完全无用的值。 从CLR的角度来看,单个托管线程在其生命周期内由几个不同的本机线程支持是完全合法的。 这意味着GetCurrentThreadId的结果可以(并且将)在线程生命周期的整个过程中发生变化。

在许多应用中,这不是可观察到的现象。 在UI应用程序中,这实际上不会发生,因为它通常由STA线程支持,由于COM互操作问题,更换(通常甚至是非法的)更难。 很多开发人员都对这一点无知。 但是,在引擎盖下更换MTA线程非常容易,这通常是后台线程的执行上下文。

由于一个原因它已经过时了; 未来的想法是“实际”线程ID可能不是常量,或者可能在.NET线程之间共享。