6

COMオブジェクトのリリースとガベージコレクションに関してSOについては多くの質問がありますが、この質問に具体的に対処するものは見つかりませんでした。

COMオブジェクト(特にこの場合はExcel Interop)を解放する場合、参照を解放してガベージコレクションを呼び出す順序はどのようにすべきですか?

いくつかの場所(ここなど)で私はこれを見ました:

Marshall.FinalReleaseComObject(obj);
GC.Collect();
GC.WaitForPendingFinalizers();

そして他の人(ここのような)ではこれ:

GC.Collect();
GC.WaitForPendingFinalizers();
Marshall.FinalReleaseComObject(obj);

それとも問題ではなく、私は何も心配していませんか?

4

2 に答える 2

4

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プログラムは終了します。それはただちに起こるのではなく、最終的には起こります。

于 2012-11-26T20:24:35.803 に答える
1

COMで使用される参照カウントメカニズムは、自動メモリ管理の別の方法ですが、メモリと動作への影響がわずかに異なります。

参照カウントの実装は、リソースのクリーンアップに決定論的な動作を提供します。Marshal.FinalReleaseComObject()これは、COMオブジェクトに関連するすべてのリソース(メモリおよびその他のリソース)への呼び出しの直後に再利用されることを意味します。

つまり、追加の管理対象オブジェクトがあり、それらをできるだけ早く再利用したい場合は、最初にCOMオブジェクトを解放し、その呼び出しGC.Collectメソッドの後でのみ解放する必要があります。

于 2012-11-26T19:58:38.970 に答える