Marshal.FinalReleaseComObject()は、基になるCOMインターフェイスポインターを解放します。
GC.Collect()およびGC.WaitForPendingFinalizers()により、COMラッパーのファイナライザーが呼び出されます。これによりFinalReleaseComObject()が呼び出されます。
したがって、意味をなさないのは、両方の方法でそれを行うことです。どちらかを選択してください。
FinalReleaseComObject()を明示的に呼び出す場合の問題は、すべてのインターフェイスポインターに対して呼び出す場合にのみ機能することです。そのうちの1つだけを見逃しても、Officeプログラムは実行を続けます。これは非常に簡単です。特に、C#バージョン4で許可されているシンタックスシュガーがそれを可能にします。のような式はrange = sheet.Cells[1, 1]
、Excelの相互運用コードで非常に一般的です。そこには、明示的にどこにも保存しない隠し範囲インターフェイス参照があります。したがって、それを解放することもできません。
これはGC.Collect()の問題ではなく、それらを見ることができます。ただし、完全に問題がないわけではありません。プログラムがインターフェイスを参照しなくなった場合にのみ、ファイナライザーを収集して実行します。これは間違いなく2番目のスニペットの何が問題なのかです。また、プログラムをデバッグするときにうまくいかない傾向がありますが、デバッガーはローカルオブジェクト参照の有効期間をメソッドの最後まで延長します。また、Taskmgrを見て、「死ぬ!」と叫ぶときも。
GC.Collect()の通常のアドバイスは、ここにも当てはまります。プログラムを実行し続け、作業を実行します。通常のことは、ガベージコレクションをトリガーし、COMラッパーも解放することです。そして、Officeプログラムは終了します。それはただちに起こるのではなく、最終的には起こります。