C# Usercontrol的内存泄漏

问题描述 投票:0回答:1

我的应用程序中存在一些严重的内存泄漏。

这是一个在内存中加载了大量东西的表单,它是一个有3个 FlowLayoutPanel. 每个面板都有很多的一个 UserControl 我已经创建了,他们只是一个带有标签的图片框。让我们称这个表格为 ColorViewer:enter image description here

每当我打开这个表格时,它占用了近300-400MB的内存,而且似乎没有释放它。

这是一张内存使用情况的图表。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;
        }
  }

这正常吗?

c# winforms memory-leaks user-controls
1个回答
0
投票

我认为你在这里没有处理任何有用的东西。

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

你只是创建了一个Bitmap类的实例(bmpTemp)(由于using语句,这个实例稍后会被处理掉),然后将同一个类的新实例分配给另一个变量(img,你正在有效使用的那个变量)。总之,即使你纠正了这一点,它也不能满足你的目的,因为处置你在PictureBox中实际显示的Image没有任何意义(而且这也会导致后面的异常)。

正如你可以在这里读到的。有必要对Image对象调用Dispose来有效地摆脱它在内存中的存在。但要注意的是,Bitmap是一个围绕未管理的GDI+位图的包装器(而且可能需要特殊的需求来处理,即使是在包装后)。

Image.Dispose()

也就是说,鉴于你提供的代码,为了从根本上切断问题,我想我可能会在ColorBox控件上实现IDisposable接口,以确保当控件被处置时总是调用Image实例的Dispose方法。

正确实现IDisposable

在你的具体情况下,我会把ImageBitmap对象视为一个完全未管理的对象,我会在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;
 }
© www.soinside.com 2019 - 2024. All rights reserved.