19

ファイナライザーは、ある時点で.NETで実行されることが保証されていますか(予備の停電など)?私はGCがどのように機能するかを知っており、正確に実行されるときは非決定的であることを知っています。

(検索では良い答えが表示されなかったので、実際の答えを見つけるのはそれほど簡単ではないことを期待してこの質問を追加します。それとは別に、私はすでに答えを知っているので、追加します誰も言及しなかった場合に備えて、数日後にそれを行います。)

4

2 に答える 2

24

レイモンド・チェンが説明するように、ファイナライザーは実際には実行されない可能性があります。彼がそれを説明してからちょうど2日後の彼の毎年恒例のCLR週の間にこの質問が尋ねられるのはちょっとおかしいです:)

怠惰なものの場合、(というよりは1つの)結論は次のとおりです。

正しく記述されたプログラムは、ファイナライザーが実行されることを想定できません。

ファイナライザーに頼ることができるかどうか疑問に思っている場合は、これがすでに知っておくべきことのすべてです。ファイナライザーに頼らないでください。

レイモンド・チェンもリンクされた記事で述べているように:

ファイナライザーはセーフティネットであり、リソース再生の主要な手段ではありません。

リソースを解放する方法を探している場合は、Disposableパターンを参照してください。


たとえば、次の場合、ファイナライザーが実行されない場合があります。

  • 別のファイナライザーが例外をスローします。
  • 別のファイナライザーには2秒以上かかります。
  • すべてのファイナライザーを合わせると40秒以上かかります。
  • AppDomainがクラッシュするか、アンロードされます(ただし、クリティカルファイナライザー(CriticalFinalizerObject、SafeHandleなど)でこれを回避できます)
  • ガベージコレクションは発生しません
  • プロセスがクラッシュする

(注:時間の値は時間の経過とともに変化する可能性がありますが、確かにしばらく前に真実でした。)

ファイナライザーが実行されない原因となる可能性のあるものは他にもたくさんあると思います。結論としては、Chen氏からの引用を除いて、ファイナライザーはバグの影響を減らすセーフティネットです。たとえば、リソースがいつかリリースされるため、明示的に行うのを忘れた場合、これは決してないよりはましです。

于 2010-08-11T12:30:07.073 に答える
6

ファイナライザーが例外をスローした場合、他のファイナライザーは実行されません。

オブジェクトを呼び出す場合は、ファイナライザーを抑制することもできSuppressFinalizerます。

MSDN(Object.Finalize)から:

Finalizeメソッドは、次の例外的な状況では、完全に実行されないか、まったく実行されない可能性があります。

  • 別のファイナライザーは無期限にブロックします(無限ループに入り、取得できないロックを取得しようとします)。ランタイムはファイナライザーを最後まで実行しようとするため、ファイナライザーが無期限にブロックされた場合、他のファイナライザーが呼び出されない可能性があります。
  • プロセスは、ランタイムにクリーンアップする機会を与えずに終了します。この場合、ランタイムのプロセス終了の最初の通知はDLL_PROCESS_DETACH通知です。
于 2010-08-11T12:27:52.447 に答える