我有一个控件泄漏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
答案 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或无。这是预期的行为。