2011-10-28 9 views
4

初めてCOMを使用する 私はこのCOM dllを持っています。たとえば、ABCServer.dllというRCWを作成し、プロジェクトの参照を追加しました。今私のアプリケーションはいくつかのスレッドを作成し、各スレッドはCOM dllから特定のクラスを作成し、それらのクラスで動作します。しかし、他のスレッドがCOM DLLから特定のクラスで作業している間、各スレッドは待機しています。COMマルチスレッドのサポート

私のアプリケーションを変更する目的は、マルチスレッドを可能にすることでした。私の側でマルチスレッドが起こっているとき、COMはそれをシーケンシャルにします。各スレッドは新しいインスタンスを作成していますが、なぜ他のスレッドが処理されるのを待っていますか?

+0

COMコンポーネントは、シングルスレッドアパートメント(STA)またはマルチスレッドアパートメント(MTA)として宣言されていますか? – Seb

+0

どうやって確認できますか? – EagerToLearn

+0

@EagerToLearn http://stackoverflow.com/questions/2722867/how-to-determine-threading-model-of-given-com-libraryを参照してください。 – shf301

答えて

1

これまでに投稿されたコメントと回答にはかなりの混乱があります。 STAまたはMTAはスレッドのプロパティです。しかし重要なのは、COMコンポーネントが必要とするものです。これはThreadingModelレジストリ値で宣言されています。あなたは "アパート"、非常に一般的な設定を見つけました。これは、コンポーネントがスレッディングをサポートしていないことを意味します。

これは.NETフレームワークの大部分のクラスと異なり、スレッドセーフであるものはほとんどありません。大きな違いは、COM スレッディングの安全性を強制していることです。 .NETクラスでは、クラスオブジェクトがスレッドセーフな方法で使用されるようにコードを記述する必要があります。それは正しい取得が難しく、バグを診断するのが非常に難しい慢性的な原因ですが、よく設計されたロックは、制限を回避することができます。これはCOMでは不可能ですが、スレッドセーフティは常に役立ちます。あなたが手伝っていても。

唯一の方法は、1つのスレッドからCOMコンポーネントを作成して使用することです。そのスレッドはSTAを選択するためにThread.SetApartmentState()で初期化する必要があります。これにより、コンポーネントの安全な避難場所を見つけるためにCOMが独自のスレッドを作成することを防ぎます。また、STAの要件であるメッセージループをポンプする必要があります。 COMコンポーネントを別のスレッドから使​​用しようとせず、コンポーネント自体がメッセージポンプを使用できるかどうかに依存しない場合は、痛いかもしれません。を避けてください。これはかなり一般的なbtwです。応答がなくなり、通常は期待どおりにイベントが発生しない場合は、イベントが発生しないことがわかります。同じスレッドからCOMオブジェクトを呼び出すだけで、独自のオブジェクトを作成する他のスレッドと並行性を得ることができます。これは通常、有用ではありません。

4

COMコンポーネントがSTA (single-threaded apartment)とマークされている場合は、マルチスレッドにすることはできません。コンポーネントの要件は、STAが実行されているスレッドにすべての呼び出しがシリアル化され、COMによって自動的に処理されることです。

コンポーネントがSTAコンポーネントである場合、言った(とそれがあるようにそれはそう)、あなたはmulti-threaded apartment component (MTA)またはより良い、free-threaded(ので、すべてのアパートメント間でマーシャリングが存在しない)ためであると、それを変更することはできませんa)VB6で書かれている、またはb)サードパーティ製のdllだから、何らかのキューモデルを扱うほうが良いかもしれません。

基本的には、すべてのの作業を非同期で実行してから、できるだけ早くこのコンポーネントを1つずつ呼び出す要求を消費するスレッド(またはプロセス、それはあなた次第です)を持ちますこのコンポーネントの複数のインスタンスを複数のスレッドでインスタンス化することができます。ApartmentState property on the Thread classApartmentState.STAに設定してから、イベント/コールバックを発行してコールが完了したら、他の作業を非同期で続行するだけです。

基本的には、2つのプロデューサ/コンシューマの実装、1つはCOMコンポーネントへの呼び出しのディスパッチ、もう1つは完了時に結果のディスパッチが必要です。

1

各スレッドがアパートメントモデルオブジェクトの独自のインスタンスを作成していて、各スレッドがSTAで動作するようにマークされている場合は、各スレッドは個別のSTAに属していて、別々のSTAで。

他の回答は、あなたのCOMインスタンスはすべて同じアパートメントにあると思います。 Thread.SetApartmentState()を呼び出してCOMオブジェクトインスタンスを作成する前に各スレッドがSTA内にあることを確認すると、そのスレッドのCOMオブジェクトは他のスレッドのSTAとは別のスレッドのSTAに存在する必要があります。したがって、異なるSTAのオブジェクトへの呼び出しのシリアル化は表示されません。

+0

私は最新の調査結果を伝えますが、COM DLLはJVMを使用してサーバーに接続し、要求/応答ファイルを送信/受信します。アプリケーションのインスタンスを2つ実行すると、リモート・サーバー・ログには2つのセッションが作成され、アプリケーションの1つのインスタンスで複数の要求を使用すると、要求がサーバーに送信されます。 1つのセッションのみが作成されます。何百万もの理由があることは知っていますが、エキスパートが雄大な目になるかもしれません。 – EagerToLearn

+0

すべてのCOMオブジェクトが同じSTAにあって呼び出しがシリアル化されていても、サーバー。プロセスごとに1つのセッションを管理しているCOMオブジェクト内にロジックがあるように聞こえます。 – Martin

+0

はい、そうです.2つのアプリケーションインスタンス(それぞれ独自のCOM参照DLLを持つ)を実行すると、2つのセッションが使用され、1つのインスタンス内で複数の要求がある場合(COM参照DLLの場合) – EagerToLearn

関連する問題