在表单中处理非托管资源

Posted

技术标签:

【中文标题】在表单中处理非托管资源【英文标题】:Disposing unmanaged resources in a form 【发布时间】:2016-08-06 10:27:43 【问题描述】:

我正在使用 Dispose 进行研发。我对处理图像资源的表单有疑问。

namespace DisposeTry

    public partial class Form1 : Form
    
        public Form1()
        
            InitializeComponent();
        

        private void Form1_Load(object sender, EventArgs e)
        
            Image mimg = new Bitmap("repository.png"))
            image1.Image = mimg;
        
    

出于显而易见的原因,我不能使用 mimg.Dispose 或包含在“使用”中。何时以及如何处置此资源。请指教。

【问题讨论】:

我不认为你可以明确地做到这一点,但垃圾收集器会处理它。在 .NET 中,当对象超出范围时,它们被分配给 Gabage 收集器,这将自动释放它们的内存。 只需添加一个 FormClosed 事件处理程序,调用 image1.Image.Dispose()。 【参考方案1】:

是的,你是对的,你需要手动处理Bitmap对象。

.NET Bitmap 类“封装了一个 GDI+ 位图”,这意味着您应该在完成后调用位图上的 Dispose,

始终在释放对图像的最后引用之前调用 Dispose。否则,在垃圾收集器调用 Image 对象的 Finalize 方法之前,它正在使用的资源不会被释放。

您可以简单地通过覆盖 Dispose 方法来做到这一点。 但是,WinForms 的问题在于,你的表单是一个分部类,其中有一部分 YourForm.Designer.cs,它是由 Visual Studio 自动生成的,并且已经实现了 Dispose 用于处置 WinForms 组件的方法。 您需要将此方法移动到您的代码中,在this SO question 中阅读更多内容。

然后,您的方法将如下所示:

protected override void Dispose(bool disposing)

  if (disposing)
  
    if (components != null)
    
      components.Dispose();
    

    mimg.Dispose(); // mimg should be global, of course
  

  base.Dispose(disposing);

【讨论】:

注意;如果您不希望一次性物品是“全局的”和/或有多个一次性物品要处理,您可以使用“全局”IList<IDisposable> 并在Dispose 内循环释放它们

以上是关于在表单中处理非托管资源的主要内容,如果未能解决你的问题,请参考以下文章

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

托管资源与非托管资源的定义

将非托管 EXE 作为资源合并到托管 C# 代码中

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

如何将非托管 C++ 表单嵌入到 .NET 应用程序中?

.net中的托管资源和非托管资源