我调试了应用程序中的资源泄漏,并创建了一个测试应用程序来测试GDI对象泄漏。在OnPaint中,我创建新图标和新位图,而不处理它们。之后,我在任务管理器中检查每种情况下GDi对象的增加情况。然而,如果我继续重新绘制应用程序的主窗口,图标的GDI对象数量会增加,但位图没有变化。图标并没有像位图一样被清理,有什么特别的原因吗?
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// 1. icon increases number of GDI objects used by this app during repaint.
//var icon = Resources.TestIcon;
//e.Graphics.DrawIcon(icon, 0, 0);
// 2. bitmap doesn't seem to have any impact (only 1 GDI object)
//var image = Resources.TestImage;
//e.Graphics.DrawImage(image, 0, 0);
}
}
测试结果:
- 没有图标和位图-30个GDI对象
- 对于位图-31 GDI对象,数字不会改变
- 使用图标-31,然后如果重新绘制窗口,则数字会增加
我认为您必须手动处理图标。我做了一些搜索,发现GC只处理位图,而不处理图标。表单有时会保留自己的图标副本(我不知道为什么)。可以在此处找到处理图标的方法:http://dotnetfacts.blogspot.com/2008/03/things-you-must-dispose.html
[DllImport("user32.dll", CharSet = CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);
private void GetHicon_Example(PaintEventArgs e)
{
// Create a Bitmap object from an image file.
Bitmap myBitmap = new Bitmap(@"c:FakePhoto.jpg");
// Draw myBitmap to the screen.
e.Graphics.DrawImage(myBitmap, 0, 0);
// Get an Hicon for myBitmap.
IntPtr Hicon = myBitmap.GetHicon();
// Create a new icon from the handle.
Icon newIcon = Icon.FromHandle(Hicon);
// Set the form Icon attribute to the new icon.
this.Icon = newIcon;
// Destroy the Icon, since the form creates
// its own copy of the icon.
DestroyIcon(newIcon.Handle);
}