2009-05-14 17 views
1

私はCOM +アプリケーションに入れられるSTA COMコンポーネントを持っています。クライアントは、そのコンポーネントにクラスのインスタンスをいくつか作成し、それらのメソッドを並行して呼び出します。クラスは正しく登録されています。対応するクラスIDの "ThreadingModel"は "Apartment"です。COM +がアパートメントスレッドモデルを無視するのはなぜですか?

同じクラスの同じメソッドのいくつかの呼び出しが、コンポーネント内部で、実際のコンポーネントコード内で並列に実行されているのがわかります。それらは同じプロセスで実行されますが、異なるスレッドで実行されます。

何が起こっているかCOM +はスレッドモデルを無視していますか? STAモデルでは一度に1つのコールしか実行できませんか?

答えて

1

混乱を避けるため、この回答では「オブジェクト」という用語を使用しません。代わりに、 "クラス"と "インスタンス"を使用しましょう。私たちは皆、彼らの違いを理解していると確信しています。

ThreadingModelが "Apartment"であるCOMクラスをマークすると、そのインスタンスがSTAにロードされることを意味します。それらのインスタンスを作成するプロセスは、すべてが同じSTAに入るのか、別々のSTAに入るのかを決定します。

発見したように、COM +はいくつかのインスタンスを別々のSTAに読み込んでいます。

STAの保証は、同時に1つのインスタンスに複数のスレッドがアクセスすることがないということです。別のSTAにロードされた場合、同じクラスの別々のインスタンスは、同時に異なるスレッドによって確実にアクセスされる可能性があります。

したがって、STAは本当にインスタンスデータを保護する方法です。あなたのクラスデータではありません。 COMコード内の「共有」データまたは「静的」データは、すべてあなたが保護する必要があります。

1

いいえ、実際はありません。 STAは文字通り「シングルスレッドアパートメント」を意味し、アパート内でスレッドを1つしか実行できないことを意味します。今問題はアパートとは何かということです。アパートメントはプロセス内の論理空間であり、実装はフレームワークによって異なる場合があります。マイクロソフトでは、STA(MicrosoftのCOMコンテキスト内)がシングルスレッドスレッドに変換されるため、アパートメントをスレッドとして実装しています。つまり、複数のアパートメント/スレッドが存在する可能性がありますが、すべてのアパートメント/スレッドはSTAの場合はシングルスレッドになります。

あなたはMTAにこれを一般化することができます。上で述べたことから、MTAはCOMコンテキストのマルチスレッドスレッドです。

+0

これは、すべての共有変数にアクセスするときに同期が必要なことを意味しますか?共有変数の同時アクセスから保護しない場合は、STAのポイントは何ですか? – sharptooth

+0

私はAamirによるこの答えが間違っていると思います。あるいは、明らかではないCOMスレッディングモデルの何かの無言の詳細に頼っていると思います。 COMの規則により、STA内のオブジェクトはそのアパートメントにあるスレッドからのメッセージのみを受信できます。私は余裕がたくさんあるとは思わない。 –

1

STAは、オブジェクトが単一の特定のスレッドからのみアクセスされることを保証します。共有変数に対する保護は必要ありません。

私はVB6のために特別なモードがありました(私はそれがどのように名付けられたか思い出しません)。COM +が専用オブジェクトを使用する複数のSTAを起動できるようにすることができます。しかし、これらのオブジェクトの変数はスレッドローカルストレージとして扱われていました。つまり、COMクラスの複数のインスタンスが複数のスレッドからアクセスされていますが、変数の共有は行われていません。この機能を使用している可能性はありますか?

+0

私は何も特別な機能を有効にしていない - ちょうど空のCOM +サーバーアプリケーションを作成し、それにコンポーネントを追加した。 – sharptooth

+0

VB6を使用していますか? –

+0

コンポーネントとクライアントの両方がATLを使用する32ビットC++です。 – sharptooth

1

他のアパートメントに住んでいるオブジェクトにオブジェクトを渡しましたか?もしそうなら、インターフェイスをマーシャリングする必要がありましたか?無料のスレッド・マーシャラーを集めたことはありますか?

大まかに言えば、あなたのオブジェクトへのインターフェイスを別のアパートメント(スレッド)のオブジェクトに渡す場合は、必ずmarshal the interfaceにする必要があります。そうしないと、呼び出しを正しく処理するプロキシを呼び出さないため、オブジェクトが他のアパートメントのオブジェクトから自由に呼び出せることがあります。

オブジェクトへのすべての呼び出しは、 スレッド(アパートメント内)で行う必要があります。 はオブジェクト を別のスレッドから直接呼び出すことは禁じられています。このフリースレッド形式の オブジェクトを使用すると、アプリケーションに問題が発生する可能性があります。 このルールの意味は、 オブジェクトのすべてのポインタは、 アパートメントの間で渡された場合、 マーシャルする必要があります。これらの機能は CoMarshalInterfaceへの呼び出しと がMSHCTX_INPROC フラグを使用する必要が CoUnmarshalInterface機能を、ラップ

* CoMarshalInterThreadInterfaceInStream marshals an interface into a stream object that is returned to the caller. 
* CoGetInterfaceAndReleaseStream unmarshals an interface pointer from a stream object and releases it. 

:COMは、この目的のために、次の 二つの機能を提供します。

+0

インターフェイスポインタはオブジェクト間を渡されません。クライアントの各インスタンスは、それが誰にも公開されない独自のインタフェースポインタを持っています。 – sharptooth

関連する問題