2009-05-05 27 views
4

我做了很好的winforms 2.0应用程序,它运行良好,客户仍然很高兴,但不幸的是,我无法解决一个问题。问题是,在使用应用程序几个小时后,gdi用户句柄数量不断上升,最终进程无法分配更多对象和应用程序崩溃...在winforms中检测gdi/user处理程序泄漏

我没有做任何事情,它是普通的应用程序,几个表单,一些更多的模式表单,一些datagridview和很多tablelayoutpanels,我添加了很多标签和文本框。

我的问题是:

  • 是否有任何“推荐做法” 关于添加/在运行时的形式消除常规系统 控制(DGV/TLP)
  • 如何检测系统处理 泄漏 - 优选地使用视觉 工作室和一种免费的插件

回答

5

检测图形和窗口汉(探查?) dle泄漏非常困难。至于在运行时找到它们的特定策略,我无法提出任何建议(尽管我很乐意听到其他人的!)。

作为防止他们,这里有一些提醒:

  • 虽然Control类的终结将调用Dispose(),这是不确定的。你不能保证任何对象都会被垃圾回收器完成。这很可能会,但这不是保证。
  • 与上述一致,表格是一个例外。当以非模式方式显示Form(意思是通过Show(),而不是ShowDialog()),然后当Form关闭时,它将确定性地呼叫Dispose()。通过ShowDialog()显示的表单必须手动调用Dispose()才能确定性清理控制手柄。
  • 记住这两件事,您可以做的最重要的事情是确保您始终在您明确创建的实现IDisposable的任何对象上调用Dispose()。这包括Form s,Control s,Graphics对象,甚至图形助手类如PenBrush。所有这些类都实现了IDisposable,并且所有这些类都需要在您不再需要时立即处理掉。
  • 尝试缓存图形工具类,假设你使用了一些。虽然PenBrush是相当轻量级创建,他们确实占用手柄,并在完成后需要处理。不是一直创建它们,而是创建一个缓存管理器,该缓存管理器允许您传入要在这些对象的构造函数中使用的参数,并保留该对象。具有相同参数的重复呼叫仍然只能使用一个实例。然后,您可以定期清理缓存或在应用程序中的特定位置刷新缓存,只要知道这些缓存的位置即可。

遵循这些准则将大大减少 - 如果不能消除 - 你的手柄泄漏。

+0

感谢您的建议。 你能推荐我任何工具/ VS插件可以帮助跟踪/检测源代码中的泄漏吗? – tomo 2009-05-06 10:32:34

+0

@tomo,再次,不,我不知道任何这样的工具。我曾经多次看过,因为我遇到了类似于你所面临的问题。解决这些问题是我引起上述提示的原因。 – 2009-05-06 13:04:36

1

我发现使用任务管理器和GDI对象列对于发现这种泄漏非常重要。您可以通过在调用之前中断来定位特定区域,记下GDI对象,然后在可疑调用之后中断以确定对象是否正确释放。

0

两个有用的GDI泄漏追踪工具的源代码可以在这里找到:link text

我已经成功地用它在许多的Visual Studio C++项目。我不确定我是否也使用.NET。