STA でのマーシャリング

STA(Single Thread Apartment)のスレッディングモデルで COM を生成して、何らかの処理を COM に投げた場合、その処理は即座に実行されるわけではなく、マーシャラーによってメッセージキューに溜められ、そのメッセージが処理されるのを待ちます。
普段はそんなことあまり意識する必要が無いのだけれども、コネクションポイントを張っている場合は注意が必要です。
何でかというと、COM 側から Sink 側へ投げる処理も、その処理を Sink 側のメッセージキューに溜めて、そのメッセージが処理されるのを待つので、

  • COM 側が Sink 側を呼び出す。
    • この要求は Sink 側のメッセージキューに溜められ、COM はその処理が完了するのを待つ。
  • Sink 側が COM 側のメソッドを呼び出す。
    • この要求は COM 側のメッセージキューに溜められ、Sink 側はその処理が完了するのを待つ。
  • どう見てもデッドロックです。本当に(ry

てなことになります。
問題としては、Sink 側が COM に呼ばれてすぐに COM のメソッドを呼び出していることにあるので、この部分を ::PostMessage() とかして、自分のメッセージキューに溜めて遅延処理を行えばいいのですが、そういった負担を強いる COM はどうかと思います。


なので、COM が Sink を呼び出す際にスレッドを生成してやり、スレッド内で Sink 側のメソッドを呼び出します。
で、メインスレッドはその処理が終わるのを待ちながら、メッセージの処理も同時に行います。
こうすることで、Sink 側の処理を行っている途中にメッセージキューに要求が溜まっても正常に処理することが可能です。


でもスレッド作るのやだなぁ……(;´Д`)


追記:
よく考えてみれば、COM から Sink を呼び出す際にメッセージキューに溜めている場合、その時点でデッドロックになる可能性もあるけれど、そんな状態になったことないような気が……。
ということは、COM から Sink を呼び出す際にはメッセージキューとは別の機構を使ってる?


追記2:
STA の場合は別スレッドから Sink を呼び出すというのが出来ないっぽい?
だとすれば MTA にするしか無いのかなぁ……(;´Д`)