6

ASP.NET MVC Web サイトをサード パーティの COM アプリケーションと統合する必要があります。コードは次のようになります。

Type type = Type.GetTypeFromProgID(progID);
dynamic obj = Activator.CreateInstance(type);
if (!obj.DBOpenedStatus)
{
    obj.InitApplicationContext();
    //do stuff with other COM objects
}

問題は、しばらくすると、COMExceptionsおそらくobj.ReleaseApplicationContext(). IDisposableそのため、コンストラクターでコンテキストを初期化し、破棄されたときにそれを解放できるように実装するラッパーを作成することを考えています。しかしlock、現在のスレッドがまだ機能している間に別のスレッドがコンテキストを閉じないようにする必要があります。コードは次のようになります。

lock (_locker)
{
    using (MyComContextWrapper comContext = new MyComContextWrapper())
    {
        //do stuff with other COM objects
    }
}

私はスレッドセーフについてほとんど知らないので、あなたに尋ねているのは次のとおりです。

  1. 私のアプローチに何か問題がありますか?
  2. 他に考慮すべきことはありますか (デッドロックなど)?
  3. 別のアプローチをお勧めしますか?

編集 1:
レジストリで COM クラスの progID を調べたところThreadingModel=Apartment、COM アプリケーションがSingle-Threaded Apartment型を使用していることがわかりました。

編集 2:
COM アプリケーションは、システムを使用してオブジェクトの ID を生成するため、これらのオブジェクトがデータベースに永続化されると、それらのオブジェクトは既に ID を持っています。このシステムには、レジストリにいくつかの情報を書き込むことが含まれます。しばらくすると、このシステムで問題が発生し、violation of primary key constraintエラーが発生し始めます。

編集 3
: System.ArgumentNullException: Value cannot be null. Parameter name: type at Activator.CreateInstance(Type type). これは、別のスレッドから新しい STA オブジェクトを作成しようとしていることが原因でしょうか?

編集 4:
の完全なスタック全体を投稿するように誰かに頼まれましたがCOMExceptions、これにより私の質問がローカライズされすぎて、私以外の誰にとっても役に立たなくなるのではないかと心配しています。さらに、実際に問題の原因を突き止めました。com オブジェクトを使用する前にコンテキストが初期化されず、システムが混乱する非常にまれなケースがいくつかありましたが、エラーは後でしか表示されませんでした。そのため、com オブジェクトを使用する前にコンテキストが常に初期化されるようにすると、問題は解決しました。

スレッドセーフと提案されたソリューションに関する回答にまだ興味があります。それとも、あまりにもローカライズされているため、質問を閉じる必要がありますか?

4

1 に答える 1

2

COM スレッディングの全体的な目的は、マルチスレッド環境での作業をより簡単かつ自動化することであるため (その使用法を理解し、レジストリが正しい場合)、オブジェクトの周りにロックを使用する必要はありません。

標準のマネージ .NET シナリオでは、ガベージ コレクターによって COM オブジェクトの解放が自動的に行われる場合でも、特に何もする必要はありません。したがって、使用パターンは必要ありません。

そうは言っても、基礎となるアンマネージ COM オブジェクトは、一度使用すると解放されるとうまく機能する可能性があります。または、アプリケーションが何らかの理由 (hi の使用など) で GC が発生するのを実際に待つことができない可能性があります。これらのシナリオでは、Marshal.ReleaseComObjectまたはMarshal.FinalReleaseComObjectを使用して、一度使用した COM オブジェクトを強制的に解放し、ラッパー オブジェクトを使用してラップすることができます。

于 2012-12-27T13:53:40.060 に答える