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