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

时间:2011-04-11 16:03:04

标签: 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);
}

2 个答案:

答案 0 :(得分:11)

投入GetCurrentThreadId是您最好的选择,并会为您提供正确的信息。

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

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

答案 1 :(得分:-1)

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