我们都知道System.IDisposable模式。它已经描述了很多时间,也在StackOverflow:
link:Dispose() for cleaning up managed resources?
Disposable模式建议我只应处理托管资源,如果我的对象被处理,而不是在最终确定期间
您可以看到发生这种情况,因为建议使用以下代码:
protected void Dispose(bool disposing)
{
if (disposing)
{
// Code to dispose the managed resources of the class
}
// Code to dispose the un-managed resources of the class
}
我知道只要我的类有一个实现System.IDisposable的(私有)成员,我的类就应该实现System.IDisposable。如果布尔值为true,则Dispose(bool)应该调用私有成员的Dispose()。
如果在最终确定期间调用Dispose,为什么会出现问题?那么,如果在finalize期间调用它,为什么下面的Dispose会成为一个问题?
protected void Dispose(bool disposing)
{
if (myDisposableObject != null)
{
myDisposableObject.Dispose();
myDisposableObject = null;
}
}
答案 0 :(得分:3)
一般来说,你应该尽快摆脱资源。如果你不需要资源,为什么要把它留在那里浪费内存?
此外,为了在完成期间调用Dispose(),您必须为对象创建一个终结器,即C#中的析构函数。但是,调用对象的终结器的确切时间是非确定性的,这意味着您的托管对象可能在那时不再安全/可访问。甚至执行终结器的线程也是非确定性的,这也可能导致难以预见的问题。
由于这些原因,应该创建终结器以仅释放非托管资源。
很少有程序员完全理解'最终确定如何运作。例如,垃圾收集器在对象实例化期间识别出您的类型具有终结器,并将您的实例放入名为finalizequeue的特殊内部数据结构中。实际上,当您使用sos.dll(windbg)调试应用程序时,您可以使用命令!finalizeQueue来显示具有终结器的对象,并且稍后将在最后确定。
答案 1 :(得分:3)
当一个对象的终结器运行时,对于它可能拥有的几乎任何IDisposable
个对象,其中一个将成立:
它只保留了对其他对象的引用,并且其他对象的终结器已经运行,因此无需对其进行任何操作。
它只保留了对该另一个对象的引用,并且计划运行其他对象的终结器,即使它还没有,并且没有必要这样做任何事情。
其他对象仍在使用IDisposable
对象,在这种情况下,终结器不得调用Dispose
。
另一个对象的Dispose
方法无法从终结器线程上下文(或者更一般地说,除了创建对象的上下文之外的任何线程上下文)安全地运行,其中如果终结者不得拨打Dispose
。
即使在上述情况都不适用的情况下,知道的代码可能会知道很多关于它的清理要求,而不是它实现IDisposable
,并且应该经常使用更详细的清理协议。