mr.*_*r.b 29 .net c# garbage-collection idisposable suppressfinalize
我有以下代码:
public void Dispose()
{
if (_instance != null)
{
_instance = null;
// Call GC.SupressFinalize to take this object off the finalization
// queue and prevent finalization code for this object from
// executing a second time.
GC.SuppressFinalize(this);
}
}
Run Code Online (Sandbox Code Playgroud)
虽然有一条评论解释了与GC相关的电话的目的,但我仍然不明白为什么会这样.
一旦所有实例都停止存在,就不会将对象注定为垃圾收集,例如,当在using
块中使用时?
什么是用例场景,它将发挥重要作用?
Dir*_*mar 34
在实现dispose模式时,您还可以向调用的类添加终结器Dispose()
.这是为了确保Dispose()
始终被调用,即使客户端忘记调用它.
要防止dispose方法运行两次(如果已经放置了对象),则添加GC.SuppressFinalize(this);
.文档提供了一个示例:
class MyResource : IDisposable
{
[...]
// This destructor will run only if the Dispose method
// does not get called.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
resource.Cleanup()
}
disposed = true;
}
}
Run Code Online (Sandbox Code Playgroud)
kic*_*sit 32
垃圾收集:GC不再引用对象时回收对象使用的内存.
Dispose:IDisposable接口中的一种方法,用于在程序员调用它时(直接或间接通过using块)释放所有托管和非托管资源.
Finalizer:释放所有非托管资源的方法.在回收内存之前由GC调用.
托管资源:实现IDisposable
接口的任何.NET类,如Streams和DbConnections.
非托管资源:托管资源类中包含的填充.Windows句柄是最简单的例子.
现在回答你的问题:
GC保留所有对象的列表(Finalization Queue),其中的类声明了Finalizer(在C#中为~ClassName).对象在创建时放入此队列中.GC定期运行以检查程序中是否有任何对象无法访问.然后,它检查是否从Finalization Queue引用了任何不可访问的对象,并将它们放在另一个名为Freacheable队列的队列中,而其余的则被回收.一个单独的线程用于运行Freacheable队列中对象的Finalize方法.
GC下次运行时,会发现以前在Freacheable队列中的一些对象已经完成,因此可以进行回收.请注意,GC需要至少两个周期(如果要进行大量的Finalization,则需要更多的周期)来摆脱具有Finalizer的对象,这会导致一些性能损失.
该SuppressFinalize
方法只是在对象标题中设置一个标志,表示不必运行Finalizer.这样GC就可以立即回收对象的内存.根据上面的定义,该Dispose
方法与Finalizer(以及更多)执行相同的操作,因此如果执行它,则不再需要Finalization.使用该SuppressFinalize
方法,您可以通过向其通知此事实来为GC保存一些工作.此外,现在您不必在Finalizer中实施检查以避免双重释放.唯一的问题Dispose
是不能保证运行,因为程序员有责任调用它,这就是为什么有时我们需要打扰终结器.
话虽如此,你很少需要编写Finalizer,因为对于绝大多数通常的非托管资源,托管包装器已经存在,并且通过Dispose
从你自己的Dispose
方法调用方法来释放托管资源,从那里来!在终结器中,您必须永远不要调用Dispose方法.
进一步阅读:
在第一次GC运行后,可以完成的对象可以使用.
通常,当GC检测到某个对象无法访问时,它会回收它.如果对象可以最终确定,那么GC不会回收它; 相反,它认为它仍然可以访问(以及该对象引用的所有对象,等等),并安排它进行最终化.只有当对象在完成后的某个时刻再次找不到时,才会回收该对象.
这意味着可终结对象会产生额外的成本:对象必须在内存中保留更长时间.因此,您看到了这样的呼叫:在不需要时禁止终结是值得的.这里,对象使用finalization来确保它总是在某个时刻被"处理掉".当它被明确地处理时,它不再需要最终确定.
归档时间: |
|
查看次数: |
23214 次 |
最近记录: |