在哪里清理处置模式中的非托管资源?

Posted

技术标签:

【中文标题】在哪里清理处置模式中的非托管资源?【英文标题】:Where to clean up unmanaged resource in dispose pattern? 【发布时间】:2019-03-18 10:05:09 【问题描述】:

我对这种模式感到困惑。

如果 disposing 为真(从 Dispose() 调用),我们将在那里释放托管对象。 如果 disposing 为 false(从 Finalizer() 调用),则访问引用的对象是不安全的,这些引用的对象是文件流等非托管对象。

如果 disposing 为真,那么我们将无法释放非托管对象? 如果 disposing 为 false,我们将无法释放托管对象?

搜索这个模式,在 Dispose(boolean) 方法中有不同的实现。 MSDN implementation

这是我从示例和教程中得到的。

protected virtual void Dispose(bool disposing)
    
        if (!disposed)
        
            if (disposing)
            
                // Free any other managed objects here.
            
            else
            
                //not safe to access referenced object
            
            // Free any unmanaged objects here.
        
        disposed = true;
    

【问题讨论】:

// Free any unmanaged objects here.“执行”disposing 是否为真。再看控制流。 ...像文件流这样的非托管对象FileStream 是一个托管对象,底层文件句柄将是非托管对象。 【参考方案1】:

在正确形成的IDisposable 模式中,true 的值disposing 意味着我们从显式的Dispose 调用或离开using 范围(这是IDisposable 消费的首选方式)到达了该方法。然而,并非所有消费者都被正确实现,为了确保我们能够在IDisposable 实现中回收所有非托管资源,我们从终结器调用Dispose(false)。所以false 中的Dispose 表明我们在完成阶段达到了这个调用,并且在这个阶段一些引用可能不可用,这就是我们使用这个标志的原因 - 区分我们在正常流程执行下可以做什么以及我们可以做什么在定稿阶段的条件下。无论此标志如何,我们都会释放非托管资源。

【讨论】:

【参考方案2】:

无论参数disposing 的值如何,都必须在方法Dispose(boolean disposing) 内完成未管理资源的清理。你可以找到more details here

【讨论】:

以上是关于在哪里清理处置模式中的非托管资源?的主要内容,如果未能解决你的问题,请参考以下文章

利用IDisposable接口构建包含非托管资源对象

在 C# 应用程序退出时清理非托管 C++ 线程

C#-C#中的Dispose模式

如何从 C# 中的非托管内存中读取数据?

C# 中的非托管 C++ 类

一个解决方案中的非托管 DLL 项目和托管 WinForms 应用程序