.net终结器总是被执行吗?

maf*_*afu 18 .net garbage-collection finalizer

终结器是否保证在某些时候在.NET中执行(备用断电等)?我知道GC是如何工作的,并且当它们完全运行时它是不确定的.

(搜索没有显示出良好的答案,所以我加入了这个问题,期望与不那么容易发现的实际答案合并.除此之外,我已经知道了答案,我将要添加几天之后如果没有人提到它.)

Ore*_*ost 24

Raymond Chen解释说,终结者实际上可能永远不会被执行.有点搞笑这个问题在他的年度CLR周期间被问到,就在他解释它的两天后:)

对于懒惰的人来说,(或者更确切地说,一个)结论是:

正确编写的程序不能假定终结器将会运行.

如果您想知道是否可以依赖终结器,这已经是您必须知道的一切:不要依赖终结器.

正如Raymond Chen在链接文章中所述:

终结者是一个安全网,而不是资源回收的主要手段.

如果您正在寻找如何释放资源,请查看Disposable模式.


例如,如果出现以下情况,终结器可能无法运行:

  • 另一个终结者抛出异常.
  • 另一个终结者需要超过2秒.
  • 所有终结器一起使用超过40秒.
  • AppDomain崩溃或被卸载(尽管你可以通过一个关键的终结器(CriticalFinalizerObject,SafeHandle或类似的东西)绕过它
  • 不会发生垃圾收集
  • 这个过程崩溃了

(注意:时间值可能会随着时间的推移而发生变化,但前段时间确实如此.)

我想还有很多东西会导致终结者永远不会跑.除了陈先生的引用之外,底线是终结者是一个减少错误影响的安全网,因为例如资源在某个时候被释放,如果你忘记明确的话,这比永远好.


Ode*_*ded 6

如果终结器抛出异常,则不会执行其他终结器.

如果调用SuppressFinalizer对象,也可以抑制终结器.

MSDN(Object.Finalize):

Finalize方法可能无法运行完成,或者在以下特殊情况下可能根本不运行:

  • 另一个终结器无限期地阻塞(进入无限循环,尝试获得它永远无法获得的锁等等).因为运行时尝试将终结器运行完成,所以如果终结器无限期地阻塞,则可能不会调用其他终结器.
  • 该过程终止而不给运行时提供清理的机会.在这种情况下,运行时的第一个进程终止通知是DLL_PROCESS_DETACH通知.