I am running some multi-threaded code that does the following.
- On an STA thread, I create a 'worker' thread, and run it.
- The STA thread then waits for the worker thread to exit.
- The worker thread calls a method on a proxy to an STA COM object on the STA thread, and then exits.
In step 2, I'm using Thread.Join()
to wait for the worker thread to exit.
The documentation for Thread.Join()
states that it blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping.
However, what happens is the worker thread blocks 'forever' on the COM call. The STA thread never services the COM call, while it is blocked on calling Thread.Join() on the worker thread.
I expected the STA thread to be able to service COM calls while blocked on Thread.Join.
Can anyone explain what might be happening here?
Here's the native callstack for the call to Thread.Join (ran VS in native code debugging mode, so differences may be due to not using WinDbg?):
ntdll.dll!_KiFastSystemCallRet@0()
ntdll.dll!_ZwWaitForMultipleObjects@20() + 0xc bytes
kernel32.dll!_WaitForMultipleObjectsEx@20() - 0x51 bytes
user32.dll!_RealMsgWaitForMultipleObjectsEx@20() + 0xd7 bytes
ole32.dll!CCliModalLoop::BlockFn() + 0x8c bytes
ole32.dll!_CoWaitForMultipleHandles@20() - 0x382a bytes
mscorwks.dll!NT5WaitRoutine() + 0x39 bytes
mscorwks.dll!MsgWaitHelper() + 0x97 bytes
mscorwks.dll!Thread::DoAppropriateAptStateWait() + 0x51ae9 bytes
mscorwks.dll!Thread::DoAppropriateWaitWorker() + 0x104 bytes
mscorwks.dll!Thread::DoAppropriateWait() + 0x40 bytes
mscorwks.dll!Thread::JoinEx() + 0x77 bytes
mscorwks.dll!ThreadNative::DoJoin() + 0xa6 bytes
mscorwks.dll!ThreadNative::Join() + 0xa8 bytes
Here is the call stack shown in the article, for STA threads that call Thread.Join: It appears to diverge from what I'm seeing on the last call.
ntdll!NtWaitForMultipleObjects+0xa
KERNEL32!WaitForMultipleObjectsEx+0x10b
USER32!RealMsgWaitForMultipleObjectsEx+0x129
USER32!MsgWaitForMultipleObjectsEx+0x46
ole32!CCliModalLoop::BlockFn+0xbb
ole32!CoWaitForMultipleHandles+0x145
mscorwks!NT5WaitRoutine+0x77
mscorwks!MsgWaitHelper+0xed
mscorwks!Thread::DoAppropriateAptStateWait+0x67
mscorwks!Thread::DoAppropriateWaitWorker+0x195
mscorwks!Thread::DoAppropriateWait+0x5c
mscorwks!Thread::JoinEx+0xa5
mscorwks!ThreadNative::DoJoin+0xda
mscorwks!ThreadNative::Join+0xfa
Here's the article's callstack for an MTA thread:
ntdll!NtWaitForMultipleObjects+0xa
KERNEL32!WaitForMultipleObjectsEx+0x10b
mscorwks!WaitForMultipleObjectsEx_SO_TOLERANT+0xc1
mscorwks!Thread::DoAppropriateAptStateWait+0x41
mscorwks!Thread::DoAppropriateWaitWorker+0x195
mscorwks!Thread::DoAppropriateWait+0x5c
mscorwks!Thread::JoinEx+0xa5
mscorwks!ThreadNative::DoJoin+0xda
mscorwks!ThreadNative::Join+0xfa