GDI处理DotNET应用程序

时间:2010-03-20 12:39:43

标签: .net memory-leaks count gdi handle

我的纯DotNET库在非托管桌面应用程序中作为插件运行。我一直在获得一个稳定的(虽然很低)崩溃报告流,似乎表明GDI句柄有问题(错误消息中的字体等恢复到系统字体,各种控件的显示中断,大规模崩溃后不久)。

我的表单几乎没有控件,但我在用户控件中做了很多GDI +绘图。什么是告诉我正在使用多少句柄,甚至泄漏的好方法?

谢谢, 大卫

7 个答案:

答案 0 :(得分:5)

从Ray Vega的回答中GDIView开始,我发现this tip

[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隐藏在后台窗口中时,我们会更新Label控件的文本。这会导致GDI泄漏字体句柄。为了解决这个问题,我们将逻辑更改为不更新UserControl,除非它当前在屏幕上可见。为了确定它是否可见,我们记录了{{1}}上次绘制的时间。

答案 1 :(得分:3)

除了性能监视器,您还可以尝试使用旧的任务管理器。

选中流程标签,然后点击View> Select Columns...并检查GDI对象。

答案 2 :(得分:3)

看一下GDIView(免费软件):

  

GDIView是一个独特的工具   GDI句柄列表(画笔,   钢笔,字体,位图等)   每个过程都打开了。它显示   每种类型的GDI的总数   处理,以及详细   有关每个句柄的信息。这个   工具对开发人员有用   需要追踪GDI资源泄漏   他们的软件。

alt text http://www.nirsoft.net/utils/gdiview.gif

注意默认情况下禁用自动刷新,但可以按特定时间间隔启用和配置:Options -> Auto Refresh -> Every [N] seconds

答案 3 :(得分:2)

我过去不得不处理同样的问题。为了检查应用程序分配的GDI对象数量,您可以使用名为GDIUsage的免费工具。

在我的情况下,应用程序崩溃了,因为它分配了超过 10.000 GDI对象,这是Windows XP中的硬限制。可能值得研究。

我在这里发表了关于这个问题的博客:
http://megakemp.com/2009/02/25/gdi-memory-leak-in-windows-forms/

答案 4 :(得分:1)

很容易从TaskMgr.exe,Processes选项卡中看到。查看+选择列,勾选GDI对象。

您的描述确实与手柄泄漏相匹配。这不应该在托管程序中真正发生,终结器应该照顾你忘记调用Dispose()。除非你不消耗大量垃圾收集堆空间。它也可能是非托管应用程序泄漏句柄,它们经常这样做。

答案 5 :(得分:1)

如果您还没有这样做,请确保在您正在使用的任何GDI +绘图对象上调用IDisposable.Dispose。通常使用C#using构造来执行此操作,例如:

using(Brush brush = ...)
{
    ...
}

静态代码分析工具(如FxCop或Visual Studio Team System版本中内置的版本)可以帮助您检测无法调用Dispose的情况。

无法以这种方式调用Dispose是一个潜在的句柄泄漏,因为在垃圾收集器看起来合适之前不会回收句柄。

答案 6 :(得分:1)

GDIObj,冯远提供的免费实用工具作为他的书Windows Graphics Programming: Win32 GDI and DirectDraw的示例程序可能会有用。

与任务管理器不同,它提供了不同GDI句柄类型的进一步细分计数,包括DC,Region,Bitmap,Palette,Font,Brush等。

(但是,它仅提供计数信息,而GDIView提供有关句柄的更多详细信息。)