VB.NET 控件 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,并且无论有多少实例都保持在那里 我创建并关闭的表单。
有任何想法吗?
谢谢 合资企业
I have a problem with a control leaking GDI handles.
This is the cut-down version of the control:
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
When I run the program, the GDI object count is 38.
Then I open a form that has only one FancyLabel on it and the GDI object count gets increased to 42.
I then close the form and the GDI count falls down to 39 and stays there no matter how many instances
of the form I create and close.
Any Ideas?
Thanks
JV
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因此,如果您连续继续执行您所描述的过程 100 次,我假设 GDI 计数不会高于 39?
如果是这样,这可能是您必须忍受的事情。 FancyLabel 所需的 GDI 对象不是 .NET 直接公开的。 我认为您能做的最好的事情就是抓住一切机会处理包含 GDI 对象的控件。 但就你的情况而言,听起来你的泄漏情况并没有那么严重,可能不值得这么麻烦。
您真正需要注意的是重复使用时不断累积和消耗 GDI 对象的泄漏。 只是为了好玩,此处列出了 GDI 对象类型。 此参考与 Windows 窗体控件没有直接关联,但您可以想象某些控件可能正在使用什么(并且我确信其他地方已对此进行了记录)。
幸运的是,微软终于在 WPF 中放弃了 GDI 对象。 纯 WPF 应用程序将仅对窗口本身使用 2 个 GDI 对象(UI 的其余部分与 GDI 无关)。 因此,如果您正处于所从事项目的开始阶段,也许现在是考虑使用 WPF 的好时机。 ;)
So if you continue the process you described 100 times in a row, I assume the GDI count would go no higher than 39?
If so, this may be something you'll have to live with. The GDI objects necessary for your FancyLabel are not something that .NET exposes directly. I think the best you can do is dispose the controls that contain the GDI objects at every opportunity. But in your case, it sounds like your leak is not so bad and probably not worth the trouble.
It's the leaks that continue to build up and consume GDI objects with repeated use that you really need to look out for. Just for kicks, the GDI object types are listed here. This reference doesn't have a direct correllation to Windows Forms controls, but you can sort of imagine what some controls might be using (and I'm sure that's documented elsewhere).
Fortunately, Microsoft has finally gone away from GDI objects with WPF. A pure WPF application will only use 2 GDI objects for the window itself (the rest of the UI is GDI-free). So if you're just at the beginning stages of the project you're working on, perhaps now is a good time to consider WPF instead. ;)
设置标签字体时,GDI 对象计数会增加。 因此,如果您想删除它,可以调用该标签的 dispose 方法并将字体设置为 null 或无。 这是预期的行为。
GDI objects count increase when you set label font. So, you can call the dispose method of that label and set font as null or nothing if you want to get rid of it. This is expected behavior.
如果您将继续使用 GDI 对象,则可以使用一些泄漏检测器。 如果您使用这样的程序,您将看到完整的堆栈,其中显示每个对象的创建位置。
If you’ll continue to work with GDI-objects you can use some leak-detectors. If you use such program you’ll see full stack which show where each object was created.
由于 Windows 窗体,GDI 计数可能会增加。 当系统呈现某些控件时,Windows 窗体间接使用 GDI。 您可以使用 .NET Memory Profiler 找出泄漏所在并确定如何解决。
编辑:
GDI 对象不会被垃圾收集器自动拾取。 您应该重写 Dispose 方法并确保正确处理所有 GDI 对象。
Well the GDI count could be increasing due to windows forms. Windows forms indirectly uses GDI when the system is rendering some controls. You can use .NET Memory Profiler to find out where the leak is and determine how to solve it.
EDIT:
GDI objects are not automatically picked up by the Garbage Collector. You should override the Dispose method and ensure all GDI objects are disposed of properly.