2

こんにちは、COM初心者です。STA モードと MTA モードの両方で COM dll をテストしたいと考えています。最初の質問は、COM オブジェクトが STA と MTA の両方をサポートすることは可能ですか?

ここで、以下の STA コード スニペットを想像します。

// this is the main thread
m_IFoo;
CoInitializeEx(STA); // initialize COM in main thread
CreateInstance(m_IFoo);
m_IFoo->Bar();

CreateThread(ThreadA);
// start ThreadA

// this is secondary thread
ThreadA()
{
    CoInitializeEx(STA);
    m_IFoo->Buz(); // call m_IFoo's method directly
}

このコードは機能しますか? 基本的なことが欠けていますか?他のスレッドからの呼び出しを実行できるようにするには、メイン スレッドにウィンドウ メッセージ ループが必要であることはわかっています。私はそれについて何かしなければなりませんか?

次に、MTA のテストに進みます。上記のコードの「STA」を「MTA」に置き換えるだけで機能しますか?</p>

別の質問: GUI を使用するスレッドは STA でなければならないため、GUI スレッドで MTA を初期化してテストすることはできませんか?

事前に感謝し、COM とスレッドについて素朴で申し訳ありません。

4

2 に答える 2

4

あるSTAから別のSTAに直接ポインタを渡すため、コードは正当なCOMではありません。COMでは許可されていません。

COMでは、インターフェイスポインタには「アパートアフィニティ」があり、アパート内でのみ使用できます。あるSTAから別のSTAに、またはSTAとMTAの間でポインタを渡すには、ポインタを安全な表現に「マーシャリング」する必要があります。その後、受信スレッドによってマーシャリングが解除されます。

これを行う最も簡単な方法は、グローバルインターフェイステーブルを使用することです。インターフェイスを1つのスレッドに登録し、DWORDを取得します。これを他のスレッドで使用して、他のスレッドが使用できるインターフェイスのバージョンを取得します。

両方のスレッドがMTAの場合、これを回避できます。STAはスレッドごとに1つですが、各STAスレッドには独自のパーティションがありますが、MTAはすべてのMTAスレッドで共有されます。これは、MTAスレッドがそれらの間でCOMポインターを自由に渡すことができることを意味します。(ただし、STAスレッドとの間でポインターを渡す場合は、マーシャリングする必要があります。)

一般的に、STAとMTAの間でコードを変更することはありません。通常、最初に一度これを決定します。スレッドにUIがある場合は、メッセージループが必要であり、通常はSTAです。UIがない場合は、MTAを使用することを決定できます。ただし、その決定を行ってコードを記述した後、どちらかを選択するとコードに影響する要件と前提条件が異なるため、後でもう一方に変更することはめったにありません。STAからMTAに、またはその逆に変更すると、コードを注意深く確認し、ポインターの割り当てなどを変更する必要があるかどうかを確認する必要があります。

于 2011-06-06T22:06:47.307 に答える
2

「MTA」から「STA」に切り替えることができるかどうか、およびそのような切り替えの結果は、オブジェクトがシステムレジストリにどのように登録されているかによって異なります。オブジェクトがマーシャリングせずに両方のケースを「サポート」するには、にThreadingModel設定されている必要がありBothます。

このすばらしい答えをご覧ください- 「発信者がCOMを初期化する方法に応じて」Bothを意味します。それはまさにあなたが望むものです。FreeApartment

「STA」モードの使用に関して-はい、所属するトレッドオブジェクトは、を呼び出してループ内でメッセージループを実行する必要がGetMessage()ありTranslateMesage()ますDispatchMessage()。とにかく、オブジェクトメソッドは2番目のスレッドから直接呼び出されることはなく、プロキシを経由します。詳細な説明については、この非常に優れた記事を参照してください。

于 2011-06-06T14:46:39.827 に答える