2010-08-11 169 views
16

終結器是否保證在某些時候在.NET中執行(備用停電等)?我知道GC是如何工作的,而且它確切的運行時它是不確定的。.net終結器是否始終執行?

(該搜索沒有顯示出良好的答案,所以我將這個問題與高度期望的合併與不容易發現的實際答案進行了合併,除此之外,我已經知道答案如果沒有人提及它,我會在幾天後添加它。)

回答

24

終結,實際上可能是從未執行,爲Raymond Chen explains。很有趣,在他的年度CLR周這個問題是問,僅僅兩天後,他解釋吧:)

對於懶惰的,在(或者更確切地說,一個)的結論是:

一個正確寫程序不能假定終結器將永遠運行。

如果你想知道你是否可以依靠終結器,這已經是你必須知道的一切:不要依賴終結器。

由於雷蒙德陳還指出鏈接的文章:

終結是一個安全網,而不是資源回收的主要手段。

如果您正在尋找如何釋放資源,請查看Disposable模式。


一個終結可能無法運行,例如,如果:

  • 另一終結拋出異常。
  • 另一個終結器需要2秒以上。
  • 所有終結者在一起需要超過40秒。
  • 一個AppDomain崩潰或卸載(雖然你可以用批判的終結(CriticalFinalizerObject,SafeHandle的或類似的東西)繞過這個
  • 沒有垃圾回收時
  • 的進程崩潰

(注:時間值可能會隨着時間而改變,but were certainly true some time ago

我猜還有很多事情可能導致終結者永遠不會運行,除了陳先生的引用,底線是,終結符是一個安全網在減少錯誤的影響,因爲例如資源被釋放某時,這比好,從來沒有,如果你忘記做它的明確性。

+0

你能引用更多的重要部分?是的,也許提問者期待着這個鏈接。 ;) – mafu 2010-08-11 12:33:26

+0

實際上,由於很多人問他們如何依賴終結者的行爲,我認爲我*引用了最重要的部分;)另一方面,文章中的其他框也可能很有趣。 – OregonGhost 2010-08-11 12:39:36

+0

@OregonGhost:我是否理解這個權利:如果20個終結器每個都需要1.95秒,那就是笨拙的命令,所有的都會執行 - 需要39秒。如果花費2.05秒,則跳過所有其他執行。這似乎相當破碎。相當粗暴地中斷一個需要2秒鐘以上的終結器,才能讓其他人在40秒超時的剩餘時間內運行,這將是一個很好的特性。但是在兩秒鐘後搗毀事物似乎是一種錯誤。 – supercat 2010-08-23 20:25:49

6

如果終結器引發異常,則其他終結器將不會執行。

如果您在對象上調用SuppressFinalizer,還可以禁止終結器。

MSDN(Object.Finalize):

finalize方法可能無法完成運行,或可能無法在下列特殊情況下,在所有運行:

  • 另一個終結塊無限期(去進入一個無限循環,試圖獲得它永遠不能獲得的鎖等等)。由於運行時嘗試運行終結器以完成,因此如果終結器無限期地阻塞,可能不會調用其他終結器。
  • 該過程終止而沒有給運行時間清理的機會。在這種情況下,運行時的第一個進程終止通知是DLL_PROCESS_DETACH通知。
+0

您可以添加「異常」部分的來源嗎? – mafu 2010-08-11 12:35:43

+0

請注意,「進入無限循環」在CLR實現中的意思是「需要兩秒以上」,如下所述:http://nitoprograms.blogspot.com/2009/08/finalizers-at-process- exit.html – OregonGhost 2010-08-11 12:37:27

+0

@mafutrct - 見這裏:http://stackoverflow.com/questions/1538630/exceptions-during-finalize-what-methodology-are-you-using-to-detect-garbage-co – Oded 2010-08-11 12:50:34

相關問題