VB.NET控件GDI处理泄漏?

时间:2009-07-28 16:20:37

标签: .net vb.net winforms gdi+

我有一个控件泄漏GDI句柄的问题。 这是控件的简化版本:

Public Class FancyLabel
    Inherits Label

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
        MyBase.OnPaint(e)
    End Sub

End Class


当我运行程序时,GDI对象计数为38。

然后我打开一个只有一个FancyLabel的表单,GDI对象计数增加到42.

然后我关闭表格,GDI计数降到39并且无论有多少实例都会停留在那里 我创建和关闭的形式。

任何想法?

由于 JV

4 个答案:

答案 0 :(得分:1)

由于Windows窗体,GDI计数可能会增加。当系统呈现某些控件时,Windows窗体间接使用GDI。您可以使用.NET Memory Profiler找出泄漏的位置并确定如何解决。

<强> 编辑: 垃圾收集器不会自动拾取GDI对象。您应该覆盖Dispose方法并确保正确处理所有GDI对象。

答案 1 :(得分:1)

因此,如果您继续连续描述100次,我认为GDI计数不会高于39?

如果是这样,这可能是你必须要忍受的。 FancyLabel所需的GDI对象不是.NET直接公开的对象。我认为你能做的最好的就是在每个机会处置包含GDI对象的控件。但在你的情况下,听起来你的泄漏并不是那么糟糕,可能不值得麻烦。

这是泄漏,继续积累并消耗GDI对象,重复使用,你真的需要注意。仅仅为了踢,列出了here的GDI对象类型。此引用与Windows窗体控件没有直接关联,但您可以想象一些控件可能正在使用的内容(我确信它已在其他地方记录)。

幸运的是,微软最终放弃了使用WPF的GDI对象。纯WPF应用程序将仅为窗口本身使用2个GDI对象(UI的其余部分不含GDI)。因此,如果您刚刚开始正在进行项目的开始阶段,那么现在可能是考虑使用WPF的好时机。 ;)

答案 2 :(得分:0)

如果您继续使用GDI对象,可以使用一些检漏仪。如果你使用这样的程序,你会看到完整的堆栈,显示每个对象的创建位置。

答案 3 :(得分:-1)

设置标签字体时,GDI对象数会增加。因此,如果要删除它,可以调用该标签的dispose方法并将字体设置为null或无。这是预期的行为。