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