终结器是否可以保证在某些时候在.NET中执行(备用电源中断等)?我知道GC是如何工作的,并且当它们完全运行时它是不确定的。
(搜索没有显示出好的答案,所以我加入了这个问题,期望与不那么容易发现的实际答案合并。除此之外,我已经知道了如果没有人提及它,我会回答并在几天之后添加它。)
答案 0 :(得分:24)
终结者实际上可能从未执行,Raymond Chen explains。有趣的是,这个问题在他的年度CLR周期间被问到,就在他解释它的两天后:)
对于懒惰的人来说,(或者更确切地说,一个)结论是:
正确编写的程序不能假定终结器将会运行。
如果您想知道是否可以依赖终结器,这已经是您必须知道的一切:不要依赖终结器。
正如Raymond Chen在链接文章中所述:
终结者是一个安全网,而不是资源回收的主要手段。
如果您正在寻找如何释放资源,请查看一次性模式。
终结器可能无法运行,例如,如果:
(注意:时间值可能随时间变化but were certainly true some time ago。)
我想还有很多东西会导致终结者永远不会跑。除了陈先生的引言之外,底线是终结者是一个安全网,可以减少错误的影响,因为例如资源有时被释放, 永远不会,如果你忘了明白这一点。
答案 1 :(得分:6)
如果终结器抛出异常,则其他终结器将不会执行。
如果您在对象上调用SuppressFinalizer
,也可以取消终结器。
来自MSDN(Object.Finalize):
在以下特殊情况下,Finalize方法可能无法完成或根本无法运行:
- 另一个终结器无限期地阻塞(进入无限循环,尝试获得它永远无法获得的锁等等)。因为运行时尝试将终结器运行完成,所以如果终结器无限期地阻塞,则可能不会调用其他终结器。
- 该过程终止,而不给运行时提供清理的机会。在这种情况下,运行时的第一个进程终止通知是DLL_PROCESS_DETACH通知。