There are times when I’ve needed to find the managed thread object backing the native object output in !threads.  The way I used to get it was to dump all thread objects (!dumpheap -mt <thread MT>) and match the managed thread Id field with the output from !threads.  However, there’s a better way. 

There’s a method on the native thread object “clr!Thread::GetExposedObjectRaw”, which is a simple 3 instruction method.  Disassembling it we can see that a pointer to the managed thread object is 0x228 bytes into the native thread object.  So, simply, the managed thread object is @ poi(poi(ThreadObj+0x228)).

I assume this is also there in the 2.0 CLR but I haven’t looked.  Also, this offset is for the 64 bit CLR, on a 32 bit system it’s at ThreadObj+0x160.  Obviously these offsets are subject to change with any CLR patch, so don’t depend on them in any production code unless you understand the risks.