views:

5177

answers:

9

In C# when deubgging threads for example, you can see each thread's ID. But I couldn't find a way to get that same thread, programmatically. And I couldn't even get the id of the current thread (in the properties of the Thread.currentThread). So I wonder how does Visual Studio get the ids of the threads, and if there's a way to get the handle of the thread with id 2345 for example?

+5  A: 

To get the OS ID use:

AppDomain.GetCurrentThreadId()
Mark Byers
GetHashCode isn't necessarily unique! and should not use it to identify a thread.
Dror Helper
You could use AppDomain.GetCurrentThreadId() if you want the OS thread ID, but multiple .NET threads could in theory share the same OS thread. Thread.GetHashCode() is guaranteed to return a value that is unique process-wide, which is what you probably want.
Mark Byers
Perhaps 'AppDomain.GetCurrentThreadId();' would have been a better answer to this question. Should I answer the question twice? Delete this? Or someone should suggest this, then I will vote them up. :)
Mark Byers
Feels dirty... none of the comments here make sense now.
Mark Byers
The method is marked as deprecated, and with good reason. Please see my answer and configurator's for the fuller picture.
Programming Hero
Well this is the only way to get to the OS Thread ID. And this should be marked as the correct answer.Even though that i'm not going to rely on this any more.
LolaRun
+1  A: 

System.Threading.Thread.CurrentThread.Name

System.Threading.Thread.CurrentThread.ManagedThreadId
Manu
That is not the ID of the thread.
Brian Rasmussen
+4  A: 

GetThreadId returns the ID of a given native thread. There's ways to make it work with managed threads, I'm sure, all you need to find is the thread handle and pass it to that function.

GetCurrentThreadId returns the ID of the current thread.

Blindy
Well If there's a managed answer without dllimport, i'll have to accept his answer. But thanks a lot for the effort. And i might actually use your answer since it is reliable.
LolaRun
This is closer to the real thing (read the native side) since managed threads can be translated to fibers running on one native thread, and since you mentioned the vs debugger, this is probably what you want.
Blindy
+2  A: 

To find the current thread Id use - `Thread.CurrentThread.ManagedThreadId'. But in this case you might need the current win32 thread id - use pInvoke to get it with this function:

[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();

First you'll need to save the managed thread id and win32 thread id connection - use a dictionary that maps a win32 id to managed thread.

Then to find a thread by it's id iterate over the process's thread using Process.GetCurrentProcess().Threads and find the thread with that id:

foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
{
     var managedThread = win32ToManagedThread[thread.id];
     if((managedThread.ManagedThreadId == threadId)
     {
         return managedThread;
     }
}
Dror Helper
I believe the OP is asking for the OS ID of the thread, which is not the same as the managed thread ID.
Brian Rasmussen
This code does not work: Process.Threads returns a collection of `ProcessThread` objects, this is not the same as (nor does it inherit) `Thread`: `(thread as Thread)` will return a null reference.
Fredrik Mörk
I've noticed that code code had a few bugs - fixed it try it now
Dror Helper
+1  A: 

From managed code you have access to instances of the Thread type for each managed thread. Thread encapsulates the concept of an OS thread and as of the current CLR there's a one-to-one correspondance with managed threads and OS threads. However, this is an implementation detail, that may change in the future.

The ID displayed by Visual Studio is actually the OS thread ID. This is not the same as the managed thread ID as suggested by several replies.

The Thread type does include a private IntPtr member field called DONT_USE_InternalThread, which points to the underlying OS structure. However, as this is really an implementation detail it is not advisable to pursue this IMO. And the name sort of indicates that you shouldn't rely on this.

Brian Rasmussen
To use GetThreadId you'd need the handle - which you get from the DONT_USE field.
configurator
I know, but as I said you can't really count on the fact that managed threads maps directly to OS threads, so I wouldn't count on it.
Brian Rasmussen
Thanks a lot for the clarification, and summurizing the problem.But now if multiple managed threads can correspond to a single OS thread (As configurator stated - and he's thanked), that means that VS is showing OS threads and not Managed Threads.
LolaRun
@OhrmaZd: Yes, VS2005/2008 shows OS IDs for managed threads in the Threads window. VS2010B2 actually shows both OS and managed ID per thread.
Brian Rasmussen
@Brian Rasmussen: Now that's an identification for a managed thread! Thanks for sharing your knowledge.
LolaRun
+9  A: 

According to MSDN:

An operating-system ThreadId has no fixed relationship to a managed thread, because an unmanaged host can control the relationship between managed and unmanaged threads. Specifically, a sophisticated host can use the CLR Hosting API to schedule many managed threads against the same operating system thread, or to move a managed thread between different operating system threads.

So basically, the Thread object does not necessarily correspond to an OS thread - which is why it doesn't have the native ID exposed.

configurator
@Configurator: Debug/Threads window in VS2010 shows "Managed thread ID". How can I get this one?
Pavel Radzivilovsky
Use the ManagedThreadID property http://msdn.microsoft.com/en-us/library/system.threading.thread.managedthreadid.aspx . This isn't the same as the OS thread ID though.
configurator
+10  A: 

You can use the deprecated AppDomain.GetCurrentThreadId to get the ID of the currently running thread. This method uses a PInvoke to the Win32 API method GetCurrentThreadID, and will return the Windows thread ID.

This method is marked as deprecated because the .NET Thread object does not correspond to a single Windows thread, and as such there is no stable ID which can be returned by Windows for a given .NET thread.

See configurator's answer for more reasons why this is the case.

Programming Hero
+1  A: 

This should get you the current thread id. ManagedThreadId is a member of Thread so you can get this from any thread.

Thread.CurrentThread.ManagedThreadId

To get a thread by it's ID, you can try a bit of linq

int threadIdWant = 2345;
Thread myThread = (from Thread entry in Process.GetCurrentProcess().Threads
   where entry.ManagedThreadId == threadIdWant
   select entry).First();
badbod99
+1  A: 

If it is valid for VS studio to display unmanaged thread ids in the Threads debug window... then why isn't it valid for me to want to access this id sometimes? For example, I might like to write a simple trace message to a debug window that displays both the managed and unmanaged thread ids, so when I break in the debugger I can see which trace statements were written by each of my threads. If I am interested in what a particular thread is doing based on the trace messages it has written, I can go to the threads window, identify the thread of interest by it's unmanaged thread id, switch to it and then inspect it's call stack, local variables etc, etc... If I can only write the managed thread ids into the trace messages, then I cannot identify which thread is which in the Threads window.

For M$ to stop us from accessing this unmanaged thread id is daft. We are big boys. We can handle the fact that it's not always a stable identifier for a managed thread. Oooooooh!! How scary!!!

Tim