【问题标题】:What to do about "Error creating window handle" errors in a C# application?如何处理 C# 应用程序中的“创建窗口句柄时出错”错误?
【发布时间】:2010-10-06 01:42:11
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • "这只是我想在 WPF 中重建此 UI 的众多原因之一。" 顺便说一下,当我在谷歌上搜索字符串时,我登陆了这个页面“创建窗口句柄 WPF 时出错”。我在 WPF 应用程序中遇到了这个错误。 :)
  • 也许我说得太早了。我的错误是由 WPF 应用程序中托管的 WinForms 控件(PropertyGrid)生成的。

标签: c# controls user-interface window-handles


【解决方案1】:

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

简短的回答:

  1. 维护一个标签页LRU cache,每当用户访问标签页时,该标签页就会更新。
  2. 在创建新标签页之前计算正在使用的窗口句柄。
  3. 如果正在使用的窗口句柄过多,请处理最近访问最少的标签页的内容,直到正在使用的窗口句柄数量降至安全水平。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      我建议考虑使用此类技术来减少控制次数。

      【讨论】:

      • 我可以看到我可以如何实现这样的东西,但它要么会极大地改变用户体验,要么需要大量的努力来处理诸如布局、焦点、标签顺序、验证等事情。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      相关资源
      最近更新 更多