【问题标题】:How to perform an operation before object is disposed?如何在处理对象之前执行操作?
【发布时间】:2010-12-02 12:49:50
【问题描述】:

使用 C#。我有一个抽象类,用于将设置读/写到 xml 文件。当不再需要该类时,我想在处理该类之前对 xml 文件执行最后一次写入操作。我尝试将此代码放入析构方法~myClass() {} 中,但它会引发异常,说明安全句柄已关闭。我猜这意味着该类已经被处置或部分处置。因此,如果析构函数不是执行此操作的正确位置,那么正确的位置在哪里?我需要实现 IDisposable 还是什么?

【问题讨论】:

    标签: c# garbage-collection dispose abstract


    【解决方案1】:

    在 C# 中没有 destructors 这样的东西。请参阅 Jon Skeet 接受的这个问题的答案,他解释并提供了一篇关于该主题的好文章。 Sample use of a C# Destructor

    此外,也许您应该考虑在您的类中实现IDisposable 接口,以便您可以执行您的操作。

    【讨论】:

    • 我认为 MS C# 标准调用/称它们为destructor。但这个名称具有误导性,因为它暗示应该在使用 C++ 析构函数的地方使用它。并且 IDisposable 对应于 C++ 析构函数,而不是终结器。
    【解决方案2】:

    SO 上的终结器上有很多线程,只需阅读其中的一些即可。

    基本的一点是你永远不应该依赖终结器,因为它们的执行顺序是未定义的或者可能根本不会运行。对于任何托管清理(您的情况),您应该使用 IDisposable,对于原生资源应该使用 SafeHandles/CriticalFinalization。

    【讨论】:

      【解决方案3】:

      听起来今天您正试图使用​​SafeHandle 字段将内容写入对象终结器中的设置文件。这不是正确的做法。

      一旦对象到达 CLR 终结器线程,所有关于对象可以看到的其他托管资源的赌注都将被取消。 SafeHandle 字段非常合法并且可能已经完成,因此在包含类的终结器运行时无效。

      处理此类场景的标准方法是实现IDisposable 并使用Dispose 方法(旨在由用户代码调用)来正确处理文件等托管资源。

      例如:

      abstract class MyClass : IDisposable { 
      
        private SafeFileHandle _handle;
      
        public void Dispose() { 
          WriteTheFile();
          _handle.Dispose();
        }
      
      }
      

      【讨论】:

      • 这个例子中使用的终结器是什么?没有理由假设_handle 的寿命比MyClass 的实例长。所以我认为代码没有区别,它只使用一个简单的无参数Dispose 调用 WriteFile 然后 _handle.Dispose
      • @CodeInChaos,这里没有优势。我最初认为它在角落场景中具有优势,但我检查了SafeHandle 的实现,这不是我想的那样,因此额外的终结器没有用处。我删除了它。
      • 什么样的角落场景?
      • @CodeInChaos,我认为SafeHandle 可能有一个终结器,它被Dispose 调用抑制,因此调用Dispose 有可能在它运行之前将其从终结队列中删除。在我进一步考虑之后,我仍然不能 100% 确定这是否是一个优势。
      【解决方案4】:

      如果您需要让终结器让您有机会在文件关闭之前编写一些东西,您需要确保对文件的强引用将比您的对象更长寿。一种方法是在静态字段中存储对文件的强引用。当对象的终结器运行时,您可以写入数据、关闭文件并将静态字段清空。请注意,如果您的终结器无法清空该字段,无论出于何种原因,该文件可能会无限期地保持打开状态。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-11
        • 2016-09-08
        • 2010-09-09
        • 2012-02-01
        • 2014-08-05
        • 1970-01-01
        相关资源
        最近更新 更多