我的应用程序中存在一些严重的内存泄漏。
这是一个在内存中加载了大量东西的表单,它是一个有3个 FlowLayoutPanel
. 每个面板都有很多的一个 UserControl
我已经创建了,他们只是一个带有标签的图片框。让我们称这个表格为 ColorViewer
:
每当我打开这个表格时,它占用了近300-400MB的内存,而且似乎没有释放它。
正如你所看到的,当我第一次打开 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;
}
}
这正常吗?
我认为你在这里没有处理任何有用的东西。
Image img;
using (var bmpTemp = new Bitmap(pathImg))
{
img = new Bitmap(pathImg);
}
你只是创建了一个Bitmap类的实例(bmpTemp)(由于using语句,这个实例稍后会被处理掉),然后将同一个类的新实例分配给另一个变量(img,你正在有效使用的那个变量)。总之,即使你纠正了这一点,它也不能满足你的目的,因为处置你在PictureBox中实际显示的Image没有任何意义(而且这也会导致后面的异常)。
正如你可以在这里读到的。有必要对Image对象调用Dispose来有效地摆脱它在内存中的存在。但要注意的是,Bitmap是一个围绕未管理的GDI+位图的包装器(而且可能需要特殊的需求来处理,即使是在包装后)。
也就是说,鉴于你提供的代码,为了从根本上切断问题,我想我可能会在ColorBox控件上实现IDisposable接口,以确保当控件被处置时总是调用Image实例的Dispose方法。
在你的具体情况下,我会把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;
}