我的纯 DotNET 库在非托管桌面应用程序中作为插件运行。我一直在收到稳定(虽然很低)的崩溃报告流,这些报告似乎表明 GDI 句柄存在问题(错误消息中的字体等。恢复为系统字体,各种控件的显示出现故障,不久后出现大规模崩溃)。
我的表单很少有控件,但我在用户控件中做了很多 GDI+ 绘图。有什么好方法可以告诉我正在使用多少个手柄,甚至泄漏?
谢谢,大卫
我的纯 DotNET 库在非托管桌面应用程序中作为插件运行。我一直在收到稳定(虽然很低)的崩溃报告流,这些报告似乎表明 GDI 句柄存在问题(错误消息中的字体等。恢复为系统字体,各种控件的显示出现故障,不久后出现大规模崩溃)。
我的表单很少有控件,但我在用户控件中做了很多 GDI+ 绘图。有什么好方法可以告诉我正在使用多少个手柄,甚至泄漏?
谢谢,大卫
从Ray Vega 的回答中的GDIView开始,我发现了这个提示:
[DllImport("User32")]
extern public static int GetGuiResources(IntPtr hProcess, int uiFlags);
public static void GetGuiResourcesGDICount()
{
//Return the count of GDI objects.
Console.WriteLine("GDICount"+GetGuiResources(System.Diagnostics.Process.GetCurrentProcess().Handle, 0));
}
private void button1_Click(object sender, System.EventArgs e)
{
GetGuiResourcesGDICount();
}
GDIView 告知泄漏的是字体对象;然后,我将调用添加GetGuiResources
到我们的日志记录代码中,以检测对象创建被触发的时间点。
在我们的例子中,Label
当控件的父级UserControl
隐藏在背景窗口中时,我们会更新控件的文本。这将导致 GDI 泄漏字体句柄。为了解决这个问题,我们将逻辑更改为不更新,Label
除非它当前在屏幕上可见。为了确定它是否可见,我们记录了UserControl
上次绘制的时间。
看看GDIView(它是免费软件):
GDIView 是一个独特的工具,它显示每个进程打开的 GDI 句柄(画笔、钢笔、字体、位图和其他)列表。它显示每种类型的 GDI 句柄的总数,以及有关每个句柄的详细信息。对于需要跟踪软件中 GDI 资源泄漏的开发人员来说,此工具非常有用。
(来源:nirsoft.net)
请注意,默认情况下禁用自动刷新,但可以为特定时间间隔启用和配置:Options -> Auto Refresh -> Every [N] seconds
除了性能监视器,您还可以尝试使用旧的任务管理器。
检查Process选项卡并单击View
>Select Columns...
并检查 GDI 对象。
过去我不得不处理同样的问题。为了检查您的应用程序分配了多少 GDI 对象,您可以使用一个名为GDIUsage的免费工具。
在我的情况下,应用程序崩溃了,因为它分配了超过10.000 个 GDI 对象,这是 Windows XP 中的硬限制。可能值得研究一下。
我在这里写过关于这个问题的博客:http:
//megakemp.com/2009/02/25/gdi-memory-leak-in-windows-forms/
从 TaskMgr.exe 的“进程”选项卡中很容易看到。查看 + 选择列,勾选 GDI 对象。
您的描述确实与句柄泄漏相符。这不应该在托管程序中真正发生,终结器应该照顾你忘记调用 Dispose()。除非你不消耗大量的垃圾收集堆空间。也可能是非托管应用程序泄漏句柄,他们经常这样做。
如果您还没有这样做,请确保在您正在使用的任何 GDI+ 绘图对象上调用 IDisposable.Dispose。您通常会使用 C#using
构造来执行此操作,例如:
using(Brush brush = ...)
{
...
}
静态代码分析工具(例如 FxCop 或 Visual Studio Team System 版本中内置的版本)可以帮助检测调用 Dispose 失败的情况。
未能以这种方式调用 Dispose 是潜在的句柄泄漏,因为在垃圾收集器认为合适之前不会回收句柄。
GDIObj是冯远提供的一个免费实用程序,作为他的书的示例程序,Windows 图形编程:Win32 GDI 和 DirectDraw可能很有用。
与任务管理器不同,它提供了对不同 GDI 句柄类型的进一步细分,包括 DC、区域、位图、调色板、字体、画笔等。
(但是,它只提供计数信息,而GDIView提供有关句柄的更多详细信息。)