COMコンポーネントをリリースする
質問
Marshal.ReleaseComObject(..)を呼び出してCOMコンポーネントが不要になった場合、Office PIAからCOMコンポーネントをリリースすることは本当に必要ですか?
このトピックに関するさまざまな矛盾したアドバイスをウェブ上で見つけました。私の意見では、Outlook PIAは常に、メソッドから値を返すようにインターフェイスへの新しい参照を返すため、明示的に解放する必要はありません。私は正しいですか?
解決
Microsoft Officeでは、一般に、参照を明示的に解放する必要があります。これは、2段階で安全に実行できます。
(1)まず、GC.Collect()を呼び出して名前付きオブジェクト変数を保持していないすべてのマイナーオブジェクトを解放し、次にGC.WaitForPendingFinalizers()を解放します。 (Visual Studio Tools for Office(VSTO)を使用している場合など、関連するオブジェクトにファイナライザーがある場合は、これを2回呼び出す必要があります。)
(2)次に、各オブジェクトでMarshall.FinalReleaseComObject()を呼び出して、名前付き変数を保持しているオブジェクトを明示的に解放します。
それだけです。 :-)
これについては、で詳しく説明しました前の投稿、およびコード例。
他のヒント
PIAは.NET相互運用ラッパーです。これは、オブジェクトのデストラクタ(またはDispose-覚えていない)でその参照カウントを自動的に処理することを意味します。秘Theは、ガベージコレクターが実行されるまで一部の参照が解放されないことです。 COMオブジェクトがインスタンス化するものに依存します。たとえば、データベースカーソルを開くCOMオブジェクトは、それらのカーソルの参照カウントが解放されるまで、それらのカーソルをメモリ内に保持します。 .NET / COM相互運用機能では、ガベージコレクターが実行されるか、Marshal.ReleaseComObject(またはFinalReleaseComObject)を使用して明示的に参照を解放するまで、参照は解放されません。
個人的にMicrosoft Office PIAを使用したことはありませんが、ほとんどの状況では、参照を明示的にリリースする必要はありません 。アプリケーションが他のリソースをロックしたりクラッシュしたりした場合にのみ、参照の不審を疑うようになります。
編集: COM / Interopオブジェクトをクリーンアップする必要がある状況に陥った場合は、Marshal.FinalReleaseComObjectを使用します。これは、1だけ減らすのではなく、参照カウントをゼロまで取得します。 -オブジェクト参照をnullに設定します。安全にしたい場合は、ガベージコレクション(GC.Collect)を明示的に強制することができますが、顕著なパフォーマンスヒットを引き起こすため、GCを頻繁に行うことに注意してください。
VS 2010については、 Marshal.ReleaseComObjectは危険と見なされますを参照してください。 。
マネージラッパーを使用して、こちらを使用することをお勧めします。チェックアウト。
それは単なる迷信かもしれませんが、Marshal.ReleaseComObject()を介してOffice PIAを明示的にリリースすることにしました。アプリケーションがクラッシュしたとき、ExcelとWordへの参照は開いたままだったからです。理由(愚かな締め切り)を深く掘り下げることはしませんでしたが、クラスの破棄パターンの一部としてそれらをリリースすると、その問題が修正されました。
この投稿。
そして、最も単純なシナリオを除き、すべてを正しく行うのは困難です。
.Net / COMの相互運用に関する簡単なルールが1つあります。疑わしい場合は、常にRelease()を使用してください。 :-)
私の経験では、そうする必要があることを示しています。そうしないと(少なくともOutlookで)アプリケーションがまったくシャットダウンしない可能性があります。
しかし、これは別のワームの缶を開きます。RCWはプロセスごとに見えるため、同じオブジェクトへの参照を持つ他のアドインを壊すことができます。
関連する質問をこちらに投稿しました、しかし、私はまだ明確な答えがありません。詳細がわかり次第、この投稿を編集します。