0

COM オブジェクトを作成するスレッド A (メイン STA スレッド) があり、それを別のスレッドに渡したいので、CoMarshalInterfaceAPI を使用します。

スレッド B (MTA/STA は関係ありません) は多くの種類のイベントを処理します。そのうちの 1 つはストリームを受信しCoUnmarshalInterface、プロキシ オブジェクトを取得するために呼び出します。

への呼び出しCoUnmarshalInterfaceは (何らかの理由で) 失敗する可能性があるため、それが発生した場合は、呼び出しCoReleaseMarshalDataてストリーム データを解放する必要がありますが、MSDN のドキュメントには次のように記載されています。

重要:オブジェクトをストリームにマーシャリングするために呼び出したCoReleaseMarshalDataのと同じアパートメントで関数を呼び出す必要があります。CoMarshalInterfaceこれを行わないと、ストリーム内のマーシャリングされたパケットが保持するオブジェクト参照がリークする可能性があります。

したがって、スレッド A では、CoMarshalInterface呼び出しの後に待機を実装し、CoUnmarshalInterface成功したかどうかを確認しましたが、待機中にスレッド B または別のスレッドがリモート com 操作を行った場合、スレッド A が結果を待機してブロックされているため、問題が発生しました。 、デッドロックが発生します。

私も運悪く使っCoWaitForMultipleHandlesてみました。

本当にCoReleaseMarshalData同じアパートに電話する必要がありますか? これを処理する別のアプローチを知っていますか?

4

1 に答える 1

0

あなたが抱えている問題は、マーシャリング自体には関係していないようです。はいCoUnmarshalInterface、作成したアパートメントからマーシャリング ストリームを解放しますが、マーシャリング自体ではなく、スレッド間の同期に問題があるようです。

したがって、スレッド A では、CoMarshalInterface 呼び出しの後に待機を実装し、CoUnmarshalInterface が成功したかどうかを確認しましたが、問題は、待機中にスレッド B または別のスレッドがリモート com 操作を行うと、スレッド A がブロックされて待機しているためです。その結果、デッドロックが発生します。

ストリームを手元に置いて別のアパートに電話をかけるとき、重要なのはあなたがどれだけ正確に待っているかです。あなたは STA にいるので、待機中 (例: を使用MsgWaitForMultipleObjectsEx) にスレッドでウィンドウ メッセージをディスパッチする必要があります。代わりに、ブロックは短期間であり、メッセージはしばらく待つことができると想定しています。次に、スレッド A でのメッセージ ディスパッチに依存する後方呼び出しがある場合、ここでデッドロックが発生します。

したがって、最初の問題は、メッセージディスパッチのブロックを含む、STA スレッドのブロックです。メッセージをディスパッチしている間待つか、後でリリースするためにストリームを安全な場所に置いてください。CoUnmarshalInterfaceそれほど急ぐ必要はありません。後で最初の都合のよいときにリソースをリリースできます。

于 2013-07-03T11:12:03.527 に答える