【发布时间】:2017-02-12 03:57:27
【问题描述】:
我最近开始分析我的 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);
}
}
【问题讨论】:
-
是什么让你认为你实际上是在泄漏内存(除了字体和画笔)? GC 只在需要时启动;所以内存使用量经常会堆积到那时..
-
我现在要关闭任务管理器。如果我不断上下滚动,它可以在 10 秒内使用 100mb 的内存。我相信它会泄漏,因为它不会在使用默认绘图时发生,只有在我控制绘图时才会发生。我还没有尝试继续超过 100+ MB 以查看它是否会达到上限。我担心由于标准表单绘制根本没有泄漏(内存使用没有随着默认绘制而攀升)
-
听起来很正常。在具有 GB RAM 且没有竞争程序的机器中,100MB 不算什么。添加缺少的 using 子句并尝试使其真正达到更大的“泄漏”..!
-
即使只有对图像列表项的绘制调用是那里的唯一代码,也会发生 100mb。我知道在上下文中使用率似乎并不高,但是为什么在使用默认绘图代码(不使用所有者绘图)时它不会爬升,但使用呢?这对我来说没有加起来
-
@TaW 原来你是对的。它一直攀升到大约 1GB 左右,然后垃圾收集器开始工作。猜猜这毕竟是正常的。我是 C# 及其内存管理的新手,所以我只是假设它最初是泄漏的。谢谢