一見 MT の問題のように見えるものに出くわしますが、COM+ で使用される STA モデルを詳細に理解しようとしています。
事実上、VB6 で記述された従来の COM+ コンポーネントがあり、C++ で記述されたネイティブ (つまり、COM ではない) Win32 DLL を呼び出します。
断続的な (そしてテストでは再現不可能な) 問題が発生したため、デバッグ コードを追加して何が起こっているのかを調べたところ、問題が発生したときにログ メッセージがファイルにインターリーブされていることがわかりました。つまり、DLL が2 つのスレッドから同時に呼び出されていました。
_getpid() と GetCurrentThreadId() に基づいてスレッドごとのファイルにログが記録されるようになったため、C++ DLL のコードが呼び出されると、同じスレッドで同時に 2 回呼び出されているように見えます。STA についての私の理解では、COM がオブジェクトの個々のインスタンスを単一のスレッドにマーシャリングし、実行を自由に中断および再開するため、これが当てはまる可能性があることが示唆されています。
残念ながら、ここからどこへ行くべきかわかりません。DllMain() で CoInitialiseEx() を呼び出して、これが STA DLL であることを COM に通知する必要があることを読んでいますが、他の場所では、これは COM DLL に対してのみ有効であり、ネイティブ DLL では効果がないと言っています。他の唯一のオプションは、DLL の一部をクリティカル セクションとしてラップして、アクセスをシリアル化することです (あごにかかるパフォーマンス ヒットはすべて受け入れます)。
DLL を作り直すことはできますが、共有状態やグローバル変数はありません。すべてがローカル変数にあるため、理論的には各呼び出しが独自のスタックを取得する必要がありますが、STA モデルが基本的にこれに奇妙な影響を与えているのではないかと考えています。別の呼び出しと同じエントリ ポイントで、既に読み込まれている DLL に再入力するだけです。残念ながら、この理論を証明またはテストする方法がわかりません。
質問は基本的に次のとおりです。
- STA COM+ コンポーネントがネイティブ DLL を呼び出すとき、アクティブな「スレッド」が中断され、DLL 呼び出しの途中で制御が別の「スレッド」に渡されるのを防ぐための STA モデルはありませんか?
- CoInitialiseEx() はこれを解決する正しい方法ですか?
- (1) も (2) も「良い」仮定ではない場合、何が起こっているのでしょうか?