如何以CLR"友好"方式获取_real_线程ID?

Hex*_*0bx 9 c# winapi

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

我发现.net的ManagedThreadId(s)不是O/S线程ID.经过一番阅读后,我遇到了AppDomain.GetCurrentThreadId().不幸的是,该功能被标记为"过时"(这可能意味着将来"不可用").我找到的一个解决方案是使用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);
}
Run Code Online (Sandbox Code Playgroud)

Jar*_*Par 11

Pinvoking into GetCurrentThreadId是您最好的选择,并会给您正确的信息.

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

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