为什么Thread.Join不允许通过COM消息?

时间:2009-08-21 15:12:41

标签: c# multithreading com clr sta

我正在运行一些执行以下操作的多线程代码。

  1. 在STA线程上,我创建了一个 '工人'线程,并运行它。
  2. STA线程然后等待工作者 线程退出。
  3. 工作线程将代理上的方法调用到STA COM STA线程上的对象,然后退出。
  4. 在第2步中,我使用Thread.Join()等待工作线程退出。

    Thread.Join()的文档指出,阻止调用线程直到线程终止,同时继续执行标准COM和SendMessage抽取

    然而,发生的是工作线程在COM调用中“永远”阻塞。 STA线程从不为COM调用提供服务,而在工作线程上调用Thread.Join()时它被阻止。

    我希望STA线程能够在Thread.Join上阻塞时为COM调用提供服务。

    任何人都可以解释这里可能发生的事情吗?

    <小时/> 这是调用Thread.Join的本机调用堆栈(在本机代码调试模式下运行VS,所以差异可能是因为没有使用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 
    

    这是调用Thread.Join的STA线程的article中显示的调用堆栈: 它似乎与我在上次电话会议上看到的情况不同。

    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
    

    这是文章的MTA线程的callstack:

    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
    

1 个答案:

答案 0 :(得分:1)

您的工作线程是否在MTA公寓中运行?如果当前公寓是MTA,则Thread.Join不会执行抽水。在这种情况下,MSDN上的文档会产生误导,因为它不是在MTA中泵入的标准。

这是一篇关于这个主题的文章

编辑重新阅读一下这个问题,看到阻塞线程是一个STA线程。将答案作为CW,以防止人们以所描述的方式解决问题