代码之家  ›  专栏  ›  技术社区  ›  Colin

如何在Windows窗体中创建GDI泄漏!

  •  3
  • Colin  · 技术社区  · 17 年前

    public partial class TestControl : UserControl
    {
        private List pens = new List();
    
        public TestControl()
        {
            InitializeComponent();
    
            for (int i = 0; i < 100; i++)
            {
                pens.Add(new Pen(new SolidBrush(Color.FromArgb(255, i * 2, i * 2, 255 - i * 2))));
            }
    
            this.Paint += new PaintEventHandler(TestControl_Paint);
        }
    
        void TestControl_Paint(object sender, PaintEventArgs e)
        {
            for (int i = 0; i < 100; i++)
            {
                e.Graphics.DrawLine(pens[i], 0, i, Width, i);
            }
        }
    }
    

    但是,当我创建对象的实例并将其添加到窗体中时,使用TaskManager查看我的应用程序时,我当前看到约37个GDI对象。如果我反复向窗体中添加新的TestObject用户控件,那么 仍然 只能看到~37个GDI对象。

    我一定是疯了。如果我不能编写一个简单的测试应用程序来创建GDI对象,我怎么能创建一个泄漏它们的应用程序呢!

    任何帮助都将不胜感激。

    谨致问候,科林E。

    6 回复  |  直到 17 年前
        1
  •  2
  •   OregonGhost    17 年前

    GDI+是否使用GDI句柄?我不确定,尽管我在某处读到有一个.NET System.Drawing实现依赖于裸GDI。

    你如何确定你的大型应用程序正在泄漏GDI句柄?任务管理器中的计数是否很大?如果是这样的话,您是一直使用GDI+,还是同时使用GDI?如果多次创建控件,测试应用程序GDI句柄计数是否会增加?

        2
  •  2
  •   DevComponents - Denis Basaric    17 年前

    for (int i = 0; i < 100; i++)
        {
            pens.Add(new Pen(new SolidBrush(Color.FromArgb(255, i * 2, i * 2, 255 - i * 2))));
        }
    

    绘制事件处理程序应如下所示:

    void TestControl_Paint(object sender, PaintEventArgs e)
    {
        for (int i = 0; i < 100; i++)
        {
            e.Graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(255, i * 2, i * 2, 255 - i * 2))), 0, i, Width, i);
        }
    }
    

    现在你每次油漆都会漏。开始最小化/还原你的窗体,然后查看GDI对象天空火箭。。。

        3
  •  2
  •   Ian Boyd    15 年前

    如果要从.NET泄漏GDI对象,则只需创建一个GDI对象而不释放它:

    [DllImport("gdi32.dll", EntryPoint="CreatePen", CharSet=CharSet.Auto, SetLastError=true, ExactSpelling=true)]
    private static extern IntPtr CreatePen(int fnStyle, int nWidth, int crColor);
    
    CreatePen(0, 0, 0); //(PS_SOLID, 0=1px wide, 0=black)
    

    Blingo blango,你把GDI笔漏了。

    为什么? 你想制造GDI泄漏。但是您的问题是如何从WinForm创建GDI泄漏—所以就是这样。

        4
  •  0
  •   Himanshu THE ONLY ONE    13 年前

    我认为编译器只使用一个句柄。


    但是如果我用WinAPI CreateFont()

        5
  •  0
  •   UnhandledExcepSean    11 年前

    在窗体上创建两个按钮。在每个按钮中,添加以下代码。在一个按钮中,注释掉Dispose方法。

        Form _test = null;
        for (int i = 0; i < 20; i++)
        {
            _test = new Form();
            _test.Visible = false;
            _test.Show();
            _test.Hide();
            _test.Dispose();
        }
    

    This 可能是我找到的最好的一页解释了。

        6
  •  0
  •   Andrew Morton    5 年前

    Using GDI Objects the Right Way

    没有显式释放的GDI对象应该由它们的finalize隐式地释放。 GDI+ FAQ )

    但我怀疑CLR垃圾收集器是否能够如此快速地删除GDI资源,以至于我们甚至看不到TaskManager中的内存使用变化。也许当前的GDI+实现没有使用GDI。

    我尝试了下面的代码来生成更多的GDI对象。但我仍然看不到GDI句柄数量的任何变化。

    void Form1_Paint(object sender, PaintEventArgs e) 
    {
        Random r = new Random();
        while (true)
        {
            for (int i = 0; i < 100; i++)
            {
                e.Graphics.DrawLine(
                new Pen(new SolidBrush(Color.FromArgb(r.Next()))), 0, i, Width, i);
            }
        }
    }
    
    推荐文章