因此,默认的处置模式实现如下所示:
class SomeClass : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
// Free any other managed objects here.
}
// Free any unmanaged objects here.
disposed = true;
}
~SomeClass()
{
Dispose(false);
}
}
据说:
如果方法调用来自终结器(即,如果处置是
false
),仅执行释放非托管资源的代码。因为 垃圾收集器销毁托管对象的顺序 未定义完成期间,使用以下命令调用此Dispose
重载 值false
阻止终结器尝试释放托管对象 可能已经被回收的资源。
问题是:为什么要假设SomeClass
对象所引用的对象可能已被释放,并且在使用该方法时我们不应该尝试处置它们从终结器调用?如果这些对象仍被我们的SomeClass
对象引用,则无法释放它们,不是吗?据说:
那些带有待定(未运行)终结器的组件将保持活动状态(暂时)并保持 放在一个特殊的队列中。 [...]在每个对象的定型器之前 运行,它仍然非常活跃-队列充当根 对象。
因此,同样,我们的SomeClass
对象被该队列引用(与根引用相同)。 SomeClass
对象所引用的其他对象也应该都有效(因为它们是通过SomeClass
对象植根的)。 然后为什么为什么以及如何在调用SomeClass
终结器时释放它们?
答案 0 :(得分:5)
Konrad Kokosa在他的书Pro .NET Memory Management中有一个令人印象深刻的解释。 (强调)
在GC期间,在Mark阶段结束时,GC检查终结队列,以查看是否有任何终结对象已死。如果有的话,它们还不能删除,因为将需要执行其终结器。因此,该对象被移动到另一个称为fReachable队列的队列。它的名字来自于这样一个事实,即它代表最终确定的可访问对象-现在仅由于最终确定而可访问的对象。如果发现任何此类对象,GC会向专用的终结器线程指示需要做的工作。
最终化线程是.NET运行时创建的另一个线程。 它从fReachable队列中一一删除对象,并调用其终结器。。 GC恢复托管线程后会发生这种情况,因为终结器代码可能需要分配对象。 由于从fReachable队列中删除了该对象的唯一根,因此下一个谴责该对象所处的世代的GC将发现它无法访问并回收它。
此外, fReachable队列被视为Mark阶段考虑的根,因为终结器线程可能不够快,无法在GC之间处理来自该终结器线程的所有对象。这使这些可终结化的对象更容易遭受中年危机的困扰-由于即将完成的终结工作,它们可能在fReachable队列中消耗了第二代资源。
我认为这里的关键是:
fReachable队列被视为Mark阶段考虑的根,因为终结器线程可能不够快,无法在GC之间处理来自该队列的所有对象。
答案 1 :(得分:0)
.NET中的对象存在,而对其存在任何引用。最后一个参考文献一经存在,它们便不复存在。对象存在时,将永远不会回收该对象使用的存储,但是在回收存储之前,GC需要执行以下几件事:
有一个特殊的列表,称为“ finalizer队列”,其中包含对已注册终结器的所有对象的引用。在确定了Universe中任何其他地方存在的所有其他引用之后,GC将检查终结器队列中的所有对象,以查看是否找到了对它们的任何引用。如果此过程使它找到以前未发现的对象,则将引用复制到另一个列表,称为“可到达队列”。每当可访问性队列为非空且没有终结器运行时,系统将从该队列中提取引用并对其调用终结器。
GC还将检查所有弱引用的目标,并使那些未被任何实时强引用标识的目标的弱引用无效。
请注意,finalize方法不会“垃圾收集”对象。取而代之的是,它延长了对象的存在,直到调用finalize
为止,目的是允许其履行对外部实体可能承担的任何义务。如果那时在宇宙中的任何地方都没有对该对象的引用,那么该对象将不复存在。
请注意,两个带有终结器的对象可能会相互保持引用。在这种情况下,终结器的运行顺序不确定。