DotNET 应用程序中的 GDI 句柄

发布于 2024-08-25 16:44:34 字数 206 浏览 8 评论 0原文

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

我的窗体几乎没有控件,但我在用户控件中进行了大量 GDI+ 绘图。有什么好方法可以知道我正在使用多少个手柄,甚至有多少个手柄泄漏?

谢谢, 大卫

My pure DotNET library runs as a plugin inside an unmanaged desktop application. I've been getting a steady (though low) stream of crash reports that seem to indicate a problem with GDI handles (fonts in error messages etc. revert to the system font, display of all sorts of controls break down, massive crash shortly after).

My Forms have few controls, but I do a lot of GDI+ drawing in User controls. What's a good way to tell how many handles I'm using, or even leaking?

Thanks,
David

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

2024-09-01 16:44:34

从 Ray Vega 的答案开始,我发现 此提示

[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 上次绘制的时间。

Starting with GDIView from Ray Vega's answer, I found 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 informed that it was font objects that were being leaked; I then added calls to GetGuiResources into our logging code to detect at which point the object creation was being triggered.

In our case, we had the text of a Label control being updated when its parent UserControl was hidden in a background window. This would cause GDI to leak font handles. To fix it, we changed our logic to not update the Label unless it was currently visible on screen. To determine whether it was visible, we keep a record of when the UserControl was last painted.

九歌凝 2024-09-01 16:44:34

看一下 GDIView (它是免费软件):

GDIView是一个独特的显示工具
GDI 句柄列表(画笔、
笔、字体、位图等)
由每个进程打开。它显示
每种类型的 GDI 的总数
处理方式以及详细信息
有关每个句柄的信息。这
工具对于开发人员来说非常有用
需要跟踪GDI资源泄漏
他们的软件。

替代文本
(来源:nirsoft.net

注意 默认情况下禁用自动刷新,但可以启用并配置特定时间间隔:Options ->自动刷新->每[N]秒

Take a look at the GDIView (it's freeware):

GDIView is a unique tool that displays
the list of GDI handles (brushes,
pens, fonts, bitmaps, and others)
opened by every process. It displays
the total count for each type of GDI
handle, as well as detailed
information about each handle. This
tool can be useful for developers that
need to trace GDI resources leak in
their software.

alt text
(source: nirsoft.net)

Note that the auto-refresh is disabled by default, but it can enabled and configured for specific intervals: Options -> Auto Refresh -> Every [N] seconds

滥情稳全场 2024-09-01 16:44:34

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

检查处理选项卡,然后单击查看 > 选择列... 并检查 GDI 对象。

Besides the performance monitor, you can try the good old Task Manager.

Check the Process tab and click View > Select Columns... and check the GDI objects.

友谊不毕业 2024-09-01 16:44:34

我过去也曾遇到过同样的问题。为了检查您的应用程序分配了多少 GDI 对象,您可以使用名为 GDI使用

在我的例子中,应用程序崩溃是因为它分配了超过 10.000 个 GDI 对象,这是 Windows XP 中的硬限制。也许值得研究一下。

我已经在博客中讨论了这个问题:
http://megakemp.com/2009/02 /25/gdi-内存泄漏-windows-forms/

I've had to deal with the same kind of problem in the past. In order to inspect how many GDI objects your application is allocating you can use a free tool called GDIUsage.

In my case the application was crashing because it was allocating more than 10.000 GDI objects, which is a hard limit in Windows XP. It might be worth looking into it.

I've blogged about this problem here:
http://megakemp.com/2009/02/25/gdi-memory-leak-in-windows-forms/

递刀给你 2024-09-01 16:44:34

从 TaskMgr.exe 的“进程”选项卡中很容易看到。查看+选择列,勾选GDI对象。

您的描述确实符合句柄泄漏。这实际上不应该发生在托管程序中,终结器应该照顾您忘记调用 Dispose() 的情况。除非你不消耗大量垃圾收集堆空间。也可能是非托管应用程序泄漏句柄,他们经常这样做。

It is easy to see from TaskMgr.exe, Processes tab. View + Select Columns, tick GDI Objects.

Your description indeed matches a handle leak. That shouldn't really happen in a managed program, the finalizer should take care of you forgetting to call Dispose(). Unless you don't consume a lot of garbage collected heap space. It could also be the unmanaged app leaking handles, they very often do.

暮色兮凉城 2024-09-01 16:44:34

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

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

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

未能以这种方式调用 Dispose 可能会导致句柄泄漏,因为在垃圾收集器认为合适之前,句柄不会被回收。

If you are not already doing so, make sure you call IDisposable.Dispose on any GDI+ drawing objects you are using. You would usually do this with the C# using construct, e.g.:

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

Static code analysis tools such as FxCop or the version built into Team System editions of Visual Studio can help to detect cases where you fail to call Dispose.

Failure to call Dispose in this way is a potential handle leak, as the handle won't be reclaimed until the garbage collector sees fit.

从此见与不见 2024-09-01 16:44:34

GDIObj,冯远提供的免费实用程序,作为他的书的示例程序,Windows图形编程:Win32 GDI和DirectDraw可能有用。

与任务管理器不同,它提供了不同 GDI 句柄类型的进一步细分的计数,包括 DC、区域、位图、调色板、字体、画笔等。

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

GDIObj, a free utility provided by Feng Yuan as a sample program for his book, Windows Graphics Programming: Win32 GDI and DirectDraw might be useful.

Unlike Task Manager, it provides counts of a further breakdown of different GDI handle types including DC, Region, Bitmap, Palette, Font, Brush, etc.

(However, it only provides count info while GDIView provides more detail about the handles.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文