C#Usercontrol的内存泄漏

时间:2017-06-05 14:40:58

标签: c# winforms memory-leaks user-controls

我的应用程序中存在大量内存泄漏。

这是在内存中加载大量内容的表单,它是一个包含3 FlowLayoutPanel的表单。每个面板都有很多我创建的UserControl,它们只是一个带标签的图片框。我们称之为ColorViewerenter image description here

每当我打开此表单时,它需要接近300-400 MB的内存,而且似乎不会释放它。

这是内存使用情况的图表: enter image description here

正如你可以在我第一次打开ColorViewer时,它会将所有内容加载到内存中(接近400mb),然后它就永远不会被丢弃。之后,每次打开ColorViewer时都会正确处理。

这是我用来加载表单的代码,我猜内存泄漏是在img的加载中。截至目前,我使用默认的Dispose()

//Loading of one of the three panel in the form,called 3 time when the form is opened:
                colorsViewerPanel.AddColorRange(colours.ConvertAll(x => new ColorBox(x.path_img, x.id,true)));

//Function that loads my UserControl into the panel
      public void AddColorRange(List<ColorBox> cBoxList)
        {
             flowLayoutPanel1.SuspendLayout();

             foreach (var cBox in cBoxList)
                  flowLayoutPanel1.Controls.Add(cBox);

             flowLayoutPanel1.ResumeLayout();
        }

//This is the ColorBox usercontrol's class

public string pathImg{ get; set; }
public int id{ get; set; }
public bool selected{ get; set; }

//This is the constructor for the UserControl
public ColorBox(string pathImage,int idImage,bool sel = true)
  {
        InitializeComponent();
        pathImg = pathImage;
        id = idImage;
        selected = sel;

        //Load img
        if (File.Exists(pathImg))
        {
          Image img;
          using (var bmpTemp = new Bitmap(pathImg))
          {
                img = new Bitmap(pathImg);
          }

          panelColor.BackgroundImage = img;
          panelColor.BackgroundImageLayout = ImageLayout.Stretch;
          labelColor.Text = id;
        }
  }

这是正常的吗?

1 个答案:

答案 0 :(得分:0)

我认为您没有在这里布置任何有用的东西:

 Image img;
 using (var bmpTemp = new Bitmap(pathImg))
 {
    img = new Bitmap(pathImg);
 }

您只是创建Bitmap类的实例(bmpTemp)(稍后将由于using语句而被丢弃),然后将同一类的新等距分配给另一个变量(img,即您正在使用的有效使用)。无论如何,即使您对此进行了纠正,也无法满足您的目的,因为将您实际显示的图像放置在PictureBox中没有任何意义(这也将在以后导致异常)。

如您在此处阅读的说明,有必要在Image对象上调用Dispose以有效消除其在内存中的存在,请注意,位图是非托管GDI +位图的包装(甚至可能需要特殊处理才能解决)

Image.Dispose()

也就是说,给定您提供的代码并从根本上解决了问题,我想我可能会在ColorBox控件上实现IDisposable接口,以确保在控件处于打开状态时始终调用Image实例的Dispose方法。处置:

Implement IDisposable correctly

在您的特定情况下,我会将Image / Bitmap对象视为完全不受管理的对象,并且会在Dispose方法的“如果有的话,释放本地资源”部分中释放它,以便在有人使用您的如果没有控制该对象,则只要该对象符合终结条件,则无论如何都会调用终结器。像这样:

 // The bulk of the clean-up code is implemented in Dispose(bool)
 protected virtual void Dispose(bool disposing)
 {
    if (isDisposed) return;

    if (disposing)
    {
        // free managed resources
        managedResource.Dispose();
    }

    // free native resources if there are any.
    if (!(img is null))
    {
       // Our Image.
       img.Dispose();
    }
    isDisposed = true;
 }