3

次のことを行うマルチスレッドコードを実行しています。

  1. STA スレッドで、「ワーカー」スレッドを作成して実行します。
  2. 次に、STA スレッドは、ワーカー スレッドが終了するのを待ちます。
  3. ワーカー スレッドは、プロキシ上のメソッドを STA スレッド上の STA COM オブジェクトに呼び出し、終了します。

ステップ 2 ではThread.Join()、ワーカー スレッドが終了するのを待つために使用しています。

のドキュメントには、標準の COM および SendMessage ポンピングを実行し続けながら、スレッドが終了するまで呼び出し元のスレッドをブロックするとThread.Join()記載されています。

ただし、何が起こるかというと、ワーカー スレッドは COM 呼び出しで「永久に」ブロックします。STA スレッドは COM 呼び出しを処理しませんが、ワーカー スレッドで Thread.Join() を呼び出すとブロックされます。

Thread.Join でブロックされている間、STA スレッドが 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 スレッドのコール スタックを次に示します。

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 スレッドのコールスタックは次のとおりです。

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
4

1 に答える 1

1

あなたのワーカースレッドはMTAアパートで動作していますか?現在のアパートがMTAの場合、Thread.Joinはポンピングを実行しません。この場合、MSDNのドキュメントは誤解を招く可能性があります。これは、MTAをポンプインしないことが標準であるためです。

これは主題に関する記事です

編集質問を少し読み直して、ブロッキングスレッドがSTAスレッドであることを確認しました。説明されている方法で問題にぶつかる人々を助ける場合に備えて、回答をCWとして残します

于 2009-08-21T15:19:10.907 に答える