我最近开始分析我的WinForms应用程序,并在向上和向下滚动ListView时注意到内存泄漏。
如果我不通过.OwnerDraw和DrawItem进行自己的自定义渲染,则不会发生此泄漏。
我的ListView包含一个图像,文本和一个绘制在所选对象之上的矩形。我错过了一些清理工作吗?它似乎无休止地重绘东西,这就是为什么内存使用堆积起来。
如果我不断在列表中上下滚动,它会在10秒内爬升到超过100mb的内存使用量。如果我不使用OwnerDraw,内存使用率将保持一致。
根据我见过的例子,我的用法似乎有效。
感谢您的帮助。
// ## Inside form load ## //
listView2.OwnerDraw = true;
listView2.DrawItem += new DrawListViewItemEventHandler(listView2_DrawItem);
// ## How the items are added to the ListView (in form load) ## //
// Create an image list
ImageList imageList = new ImageList();
imageList.ImageSize = new Size(256, 178);
imageList.ColorDepth = ColorDepth.Depth32Bit;
// Assign the image list to the listView
listView2.LargeImageList = imageList;
// Create an array of 20 listView items
ListViewItem[] items = new ListViewItem[20];
// Create 20 items
for (int i = 0; i < 20; i++)
{
// Add the image for this item to the image list
imageList.Images.Add(Image.FromFile("myFile2.jpg"));
// Create the item
items[i] = new ListViewItem("Item");
items[i].ImageIndex = i;
// Add the item to the listView
listView2.Items.Add(icons[i]);
}
// ## Draw item handler ## //
private void listView2_DrawItem(object sender, DrawListViewItemEventArgs e)
{
Rectangle rect3 = new Rectangle(e.Bounds.Left + 10, e.Bounds.Top + 10, 256, 178);
Rectangle rect4 = new Rectangle(rect3.Left, e.Bounds.Top, rect3.Width, e.Bounds.Height + 14);
TextFormatFlags flags = TextFormatFlags.HorizontalCenter |
TextFormatFlags.Bottom | TextFormatFlags.WordBreak;
// Draw the image for this item
e.Graphics.DrawImage(e.Item.ImageList.Images[e.ItemIndex], rect3);
// Draw the text and the surrounding rectangle.
TextRenderer.DrawText(e.Graphics, e.Item.Text, new Font("Arial", 12), rect4, Color.Black, flags);
if (e.Item.Selected)
{
int width = e.Item.ImageList.Images[e.ItemIndex].Width;
int height = e.Item.ImageList.Images[e.ItemIndex].Height;
Brush brush = new SolidBrush(Color.FromArgb(180, 1, 1, 1));
e.Graphics.FillRectangle(brush, rect3);
TextFormatFlags flags2 = TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak;
// Draw the text
TextRenderer.DrawText(e.Graphics, e.Item.Text, new Font("Arial", 12), rect3, Color.White, flags2);
}
}
答案 0 :(得分:1)
您需要处置新的字体(&#34; Arial&#34;,12)对象和画笔。
你泄漏的不仅仅是内存,你也在泄漏GDI对象。
您可以在表单加载时创建一次字体,并在表单关闭时处理它(更好的性能),或者使用需要它的DrawItem块中的using块创建和处理它(更慢,但更简单的代码)< / p>
答案 1 :(得分:0)
解决方案是使用:
this.listView2.LargeImageList.Draw(e.Graphics, gameItemRect.Left, gameItemRect.Top, gameItemRect.Width, gameItemRect.Height, e.ItemIndex);
这使用内部句柄而不是创建图像的副本。 此外,刷子和字体需要在代码块之外进行预初始化,以防止为每个绘制事件和泄漏内存重新创建它们,如@Tim所述。主内存泄漏是由于图像绘制调用。
现在内存使用情况与不使用OwnerDraw的情况一致。