4

我已经看过这个问题,并且我已经检查了那里提出的建议。我的程序创建和销毁了很多 UI 控件(很多UI 控件),任何使控件在“销毁”后仍然存在的东西都会导致这个问题。(有趣的事实:如果你在销毁它的容器之前没有将ToolStrip控件的Visible属性设置为 false,它不会被释放,因为它仍然在 Windows 中注册以接收主题更改事件;它只会在它不可见时取消注册,并且它显然无法知道在其容器被销毁时会发生这种情况。)

问题是,我的应用程序实际上有可能真的用完了窗口句柄。该程序有一个包含嵌套选项卡控件的表单。每个父选项卡有 12 或 13 个子选项卡,一个子选项卡上可以有 30 或 40 个控件。用户很可能在任何给定时间打开 15 个父选项卡,这进入了应用程序中 5000 多个实时控件的领域。而且我知道我的许多控件使用多个窗口句柄。

(在你说“好吧,看起来你的 UI 设计错了”之前,让我先放弃这一点:应用程序存在的全部原因首先是用户拥有巨大的数据空间,他们需要能够快速导航到。选项卡内的选项卡实际上对他们非常有效。)

我的理解是每个应用程序有 10,000 个窗口句柄的硬性限制。如果这确实是真的(我知道很多事情是真的而不是真的),那么我将不得不管理我的应用程序对它们的使用。例如,当我开始在窗口句柄上运行不足时,我可以丢弃最近最少使用的选项卡的内容。

但是我怎么知道我已经开始在窗口句柄上运行不足?这真的是解决问题的正确方法吗?

(这只是我想在 WPF 中重建此 UI 的众多原因之一。)

4

3 回答 3

3

最好的方法是减少句柄的数量,而不是对达到进程限制做出反应。这将提供更好的性能并且(在我看来)将更可靠。

您熟悉大多数网格控件的工作原理吗?一个网格可以有大量的单元格,但网格控件不会为每个单元格创建一个编辑框(控件)。只有一个编辑框,可以根据需要移动;如果一个单元格是一个组合框(下拉列表),则创建一个组合框并四处移动;等等。这意味着您需要绘制一些看起来像所需控件的东西,但在实际使用中您只需要一个(每个)控件。

类似地,一些选项卡控件使用单个窗口/控件,而不是为每个选项卡创建一个窗口。

我建议考虑像这样的技术来减少你的控制数量。

于 2009-02-06T23:01:23.283 回答
1

我已经解决了这个问题,我已经在这个答案中详细描述了这个问题。我在那里而不是在这里回答,主要是因为当我阅读其他对这个问题的回答时,我对 Raymond Chen 很生气。

简短的回答:

  1. 维护一个标签页的LRU 缓存,每当用户访问一个标签页时,该缓存就会更新。
  2. 在创建新标签页之前计算正在使用的窗口句柄。
  3. 如果正在使用的窗口句柄过多,则处理最近最少访问的标签页的内容,直到正在使用的窗口句柄数量下降到安全水平。
于 2009-02-11T01:00:08.033 回答
0

您可以使用无窗口控件 - 这些类型的控件不需要窗口。设计为在窗口中有大量控件的应用程序实际上应该设计为使用无窗口控件。例如,参见 Internet Explorer——在 Spy++ 中查看它——你会发现它显示的控件数量惊人地少。

当我们迁移到 .Net 时,我们发现一个有趣的事实是窗口具有线程关联性,您必须在该线程中销毁它们 - 因此,如果您只是将其留给垃圾收集(在不同的线程中运行)来清理您的控件那么窗户就不会被破坏。因此,在具有窗口的控件中,实现 IDisposable 并显式销毁它们。

您可以使用任务管理器、进程资源管理器、perfmon 等查看应用程序中存在多少 GDI 对象。窗口句柄是 GDI 对象,因此如果您看到这个计数上升到数千个,您就知道您会遇到问题。

于 2009-02-06T23:23:03.317 回答