0

COM サーバーと通信してシミュレーションを行う C# プログラムを作成しました。問題なく動作しますが、COM サーバーによって実行されるシミュレーションはかなりプロセッサを集中的に使用し、シングル コアしか実行しません。

そのため、Parallel.Forを使用してワークロードを複数のスレッドに分散しました。ただし、COM サーバーによって生成されたすべてのシミュレーション結果は、そのクラスのすべてのインスタンス間で共有されているようです。そのため、1 つのスレッドのみで並列タスクを実行すると、すべてが期待どおりに機能しますが、タスクを複数のスレッドで実行すると、結果が完全に文字化けします (複数のスレッドが原因で、シミュレーション エンジンが結果を読み取り中に新しい結果に置き換えてしまうため)。

クラス インスタンスの結果共有を停止するために、COM サーバーに複数回接続する方法があるかどうか疑問に思っていました。

編集

COM サーバーに接続するための私のプロセスは次のとおりでした。

  • Project->Add References->COM (VS2010) を使用して参照を追加します。
  • 次のコードを使用して、シミュレーター オブジェクトをインスタンス化します。

    dss = new OpenDSSengine.DSS();
    dss.Start(0);
    

上記のコードはParallel.Forのローカル スレッド データ初期化子 (localInit) パラメーターで呼び出されるため、スレッドごとに新しいdssオブジェクトが作成されますが、得られる結果はすべてのスレッドで共通のようです。

COM サーバーは dll です。

4

2 に答える 2

2

COM サーバーが実際にはインプロセス サーバー (.exe ではなく .dll) であることを指定すると、実行するnew DSS()たびに実際に新しいインスタンスが作成されることを意味します (まれなシングルトン クラス ファクトリで作成された場合を除く)。可能ですが)。

あなたの説明によると、問題は、DSS実装が静的/グローバル状態を使用しているため、実行を並列化するとデータが文字化けするという事実にあるようです。

その場合、 DllSurrogateを使用して、サーバーの各インスタンスを個別のプロセスで実行できます。デフォルトのサロゲート (dllhost.exe) では不十分な場合は、カスタム サロゲートを作成できます。サーバーを別のプロセスに移動すると、サーバーに対して実行されるメソッド呼び出しごとにマーシャリング オーバーヘッドが発生することに注意してください。

また、 STA COM サーバーを使用している場合、サーバーへのすべての呼び出しが COM インフラストラクチャによってシリアル化されるため、並列化は効果がないことに注意してください。

そうは言っても、そこに行く前に、問題が呼び出し元側にないこと、つまりサーバー自体ではなく並列化にあることを確認してください。

于 2012-10-04T14:35:44.750 に答える
1

まず、COM オブジェクトの複数のインスタンスを作成してみてください (単に new OpenDSSengine.DSS() を複数回呼び出して、結果を個別の変数または配列に格納します)。COM サーバーが適切に実装されていれば、これらの複数のインスタンスが相互に干渉することなくプロセス内に共存し、マルチスレッド クライアント コードでそれらを同時に使用できます。

それでもこれらのインスタンスが互いに干渉している場合は、COM サーバーがプロセスに対してグローバルな状態を使用していることを意味します。それを回避する唯一の方法は、他の人が示唆しているように、複数の代理プロセスを介して複数の COM オブジェクトを呼び出すことです。

于 2012-10-04T14:45:08.623 に答える