7

我们都知道 System.IDisposable 模式。它被描述了无数次,也在 StackOverflow 上:

链接: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) 应调用私有成员的 Dispose()。

如果在 finalize 期间调用 Dispose 为什么会出现问题?那么,如果在 finalize 期间调用了以下 Dispose,为什么会出现问题呢?

protected void Dispose(bool disposing)
{
    if (myDisposableObject != null)
    {
        myDisposableObject.Dispose();
        myDisposableObject = null;
    }
 }
4

2 回答 2

5

当一个对象的终结器运行时,IDisposable它可能持有的几乎所有对象都会出现以下情况之一:

  1. 它拥有对该其他对象的唯一引用,并且该其他对象的终结器已经运行,因此无需对其进行任何操作。

  2. 它拥有对该其他对象的唯一引用,并且该其他对象的终结器已计划运行,即使它还没有运行,也无需对其执行任何操作。

  3. 其他对象仍在使用该IDisposable对象,在这种情况下终结器不得调用Dispose.

  4. 另一个对象的Dispose方法不能从终结器线程上下文(或更一般地说,除了创建对象的线程上下文之外的任何线程上下文)安全地运行,在这种情况下,终结器不能调用Dispose.

即使在上述都不适用的情况下,知道这一点的代码可能会知道很多关于它的清理要求,而不是它实现的事实IDisposable,并且应该经常使用更详细的清理协议。

于 2015-07-29T16:24:13.013 回答
4

一般来说,您应该尽快摆脱资源。如果您不需要资源,为什么要保留它以浪费内存?

此外,为了在终结期间调用 Dispose(),您必须为您的对象创建终结器,即 - C# 中的析构函数。但是,调用对象终结器的确切时间是不确定的,这意味着您的托管对象可能不再安全地存在/无法访问。即使是执行终结器的线程也是不确定的,这也可能导致难以预见的问题。

由于这些原因,应该创建终结器以仅释放非托管资源。

很少有程序员能够“完全”理解最终化是如何工作的。例如,垃圾收集器在对象实例化期间识别出您的类型有一个终结器,并将您的实例放入一个称为 finalizequeue 的特殊内部数据结构中。实际上,当您使用 sos.dll (windbg) 调试您的应用程序时,您可以使用命令 !finalizeQueue 来显示具有终结器且在稍后某个时间点尚未完成的对象。

于 2015-07-29T14:44:32.840 回答