为什么Dispose()应该处置托管资源而不是终结器?
本文关键字:资源 Dispose 为什么 | 更新日期: 2023-09-27 18:05:33
我们都知道这个系统。IDisposable模式。它已经被描述过无数次了,也在这里的StackOverflow:
link: Dispose()清理托管资源?
Disposable模式建议我只在对象被处置时处置托管资源,而不是在finalize
期间处置托管资源。
您可以看到这会发生,因为建议使用以下代码:
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的(私有)成员。如果布尔值处置为真,则Dispose(bool)应调用private成员的Dispose()。
为什么在finalize过程中调用Dispose会有问题?那么,如果在finalize期间调用下面的Dispose,为什么会出现问题呢?
protected void Dispose(bool disposing)
{
if (myDisposableObject != null)
{
myDisposableObject.Dispose();
myDisposableObject = null;
}
}
当对象的终结器运行时,它可能保存的几乎所有IDisposable
对象都为下列情况之一:
-
它保存了对其他对象的唯一引用,并且其他对象的终结器已经运行,所以不需要对它做任何操作。
-
它保存了对其他对象的唯一引用,并且其他对象的终结器被计划运行,即使它还没有运行,也不需要对它做任何操作。
-
其他对象仍在使用
IDisposable
对象,在这种情况下,终结器不能调用Dispose
。 -
其他对象的
Dispose
方法不能安全地从终结器线程上下文中运行(或者,更一般地说,除了创建对象的线程上下文中),在这种情况下,终结器不能调用Dispose
。
即使在上述都不适用的情况下,知道这一点的代码也可能知道很多关于它实现IDisposable
之外的清理需求,并且应该经常使用更详细的清理协议。
一般来说,你应该尽快摆脱资源。如果不需要某个资源,为什么要保留它来浪费内存呢?
另外,为了在结束过程中调用Dispose(),您必须为对象创建一个结束器,也就是c#中的析构函数。然而,调用对象终结器的确切时间是不确定的,这意味着您的托管对象在那一刻可能不再安全。甚至执行终结器的线程也是不确定的,这也可能导致难以预见的问题。
由于这些原因,应该创建终结器来仅释放非托管资源。
很少有程序员"完全"理解最终化是如何工作的。例如,垃圾收集器在对象实例化期间识别出您的类型具有终结器,并将您的实例放入称为finalizequeue的特殊内部数据结构中。实际上,当你用sos.dll (windbg)调试你的应用程序时,你可以使用命令finalizeQueue来显示具有终结器并且在稍后的某个时间点尚未被终结的对象。