处理 Icon 和 Bitmap 有区别吗?

Posted

技术标签:

【中文标题】处理 Icon 和 Bitmap 有区别吗?【英文标题】:Is there a difference in disposing Icon and Bitmap? 【发布时间】:2015-04-14 12:40:03 【问题描述】:

我正在调试我的应用程序中的资源泄漏,并创建了一个测试应用程序来测试 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,然后如果重新绘制窗口,数字会增加。

【问题讨论】:

可能的解释是它的垃圾收集效果:Bitmap 通常是 largeIconsmall 那么大 Bitmaps 触发器up 清除Bitmaps(并dispose它们)但不清除Icons的垃圾收集 @DmitryBychenko 新创建的小对象不应该属于第 0 代并更频繁地清理吗? 是的,0代容易被收集;另一个问题是 GC 会注意 CPU 缓存大小等,因此大对象可以触发垃圾回收。 @DmitryBychenko 我想没有简单的方法可以通过实验检查这一点。顺便说一句,我使用的是小图像,它们的大小应该相差不大。 由于您显然使用的是静态资源,您是否尝试过保留位图副本并改用 DrawImage? icon.ToBitmap()。这样,您只需在代码中引用该图标一次。 【参考方案1】:

我相信您必须手动处理图标。我做了一些搜索,发现 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);

【讨论】:

以上是关于处理 Icon 和 Bitmap 有区别吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何将Icon转成Bitmap

bitmap运算

将BitMap转成Icon

将BitMap转成Icon

Icon 转 Bitmap

Redis 亿级用户信息存储实践:bitmap 位图存储