如何将 Finalize 与托管资源一起使用

本文关键字:资源 一起 Finalize | 更新日期: 2023-09-27 18:31:15

我不是100%清楚如何在B的最后一个实例完成之前

定义类A的实例存在。

或者换句话说,我希望所有 B 在 B 最终确定中调用 A 中的关闭和处置方法......并在 A 本身最终确定之前发生这种情况。

场景:

一个。我有一个非托管资源的托管包装器。 打个比方,我们称 A 为文件系统

B. 引用 A 的托管资源,而这些资源又通过 A 包装器请求了非托管资源。 对于分析,我们称 B 为文件。

附加请求 --> 我希望使用语法能够很好地发挥作用。 即显式调用使用处置不应释放非托管资源。 对象将位于对象池中。 仅当它离开对象池时,才应释放它。

class SomeClass() : IDisposable{
    public SomeClass(){}
    public ~SomeClass(){
       // dispose of unmanaged here?
    }
    // Dispose(bool disposing) executes in two distinct scenarios.
    // If disposing equals true, the method has been called directly
    // or indirectly by a user's code. Managed and unmanaged resources
    // can be disposed.
    // If disposing equals false, the method has been called by the
    // runtime from inside the finalizer and you should not reference
    // other objects. Only unmanaged resources can be disposed.
    public void Dispose(bool disposing) {
        if (disposing) {
            // dispose managed
        } else {
            // dispose unmanaged?
        }
    }
    public void Dispose() {
        Dispose(true);
        //GC.SuppressFinalize(this);
    }

}

引用:

[1] 为什么不允许覆盖 Finalize 方法

[2] CLR via C Sharp 3rd Ed. 第21章. CriticalFinalizerObject. 特别是第537页"使用托管资源的定稿"

如何将 Finalize 与托管资源一起使用

一般无法控制最终排序。不过,您可以使用 CriticalFinalizerObject 控制两阶段顺序。另请查看 SafeHandle 基础结构以及 FileStream 如何做到这一点。

如果这还不够,您可以通过从静态类成员(例如 List 或 Dictionary)创建对象引用来任意控制生存期。仅当您释放这些引用时,才能完成。因此,您将创建一个对 A 的引用,一旦您注意到对 B 的 GCHandle 已失效,您就会清除该引用。