How do I get the _real_ thread id in a CLR "friendly" way?
As an exercise I was writing some code to display the O/S processes and O/S threads within a process (like Sysinternals process explorer does).
I found that .net's ManagedThreadId(s) are not the O/S thread ids. After a bit of reading I came across AppDomain.GetCurrentThreadId(). Unfortunately, that function is marked as "obsolete" (which could mean "not available" in the future). One solution I found is to use InteropServices to directly call the Win32 GetCurrentThreadId. I am fine with that but, it feels counter to the .net philosophy.
My question is: is there a CLR "friendly" way of obtaining the real id of the current thread ?
For reference, here is a snippet of code showing what I've tried so far. // 1 and // 2 display the correct thread id, // 3 and // 4 were attempts to obtain the 开发者_高级运维same info in a CLR friendly way (but they don't work.)
Thank you for your help,
John.
[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 into the GetCurrentThreadId
is your best bet and will give you the correct information.
However I must warn you, there are very good reasons why the CLR doesn't provide this information: it's almost a completely useless value for managed code. It's perfectly legal from a CLR perspective for a single managed thread to be backed by several different native threads during it's lifetime. This means the result of GetCurrentThreadId
can (and will) change throughout the course of a thread's lifetime.
In many applications this is not an observable phenomenon. In a UI application this won't actually happen because it's typically backed by an STA thread which is harder (usually even illegal) to swap out due to COM interop issues. So many developers are blissfully ignorant of this. However it's very easy to swap out MTA threads under the hood which is typically the execution context of a background thread.
It's obsolete for a reason; the idea being in the future the 'actual' thread ID might not be constant, or might be shared between .NET threads.
I don't understand why people ask "why don't you ...". The question was how to get the REAL (operating system) thread id. And there is an important reason for it, which derives from Visual Studio itself ... it reports the ending of a thread not with the managed id, but obviously with the operating system thread id (e.g. "The Thread 0x5424 has ended with Code 0 (0x0)."). To be able to trace/follow the thread usages and endings fully, to verify your thread handling perfectly, e.g. on asynchronous methods, which return on newly created threads [e.g. TCPListener.BeginAccept => new Socket on new thread], you NEED the native thread id. After having studied as many answers about this problem as possible, in many blogs, it seems for me, as if the only reliable method to retrieve the native id of the current thread is by:
[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();
...
int nativeThreadID = GetCurrentWin32ThreadId();
精彩评论