什么是Winforms停车窗

这是对此答案的后续问题https://stackoverflow.com/a/20584601/2530848 。

我的印象是Control类没有实现真正的finailzer,所以泄漏的控件永远泄露,在最终确定期间没有清理。

Hans Passant在评论部分提供了一些提示,说明了它,以及一些关键字ParkingWindow 。 我用Google搜索了该关键字,找不到任何有用的资源。

最后我通过反编译器在System.Windows.Forms.Application.ParkingWindow找到了一个名为ParkingWindow的类,我无法理解正在做什么。

它看起来像无人看管的窗户将成为这个停车窗口的父级,并在某些时候被摧毁,但不确定。

问题究竟是什么ParkingWindow及其用途是什么?

编辑:这与Control的Finalization或cleanup有什么关系?

后来在某些时候被摧毁但不确定

“不确定”是问题的症结所在。 这种情况经常出错,窗户根本没有被破坏。

Shawn Farka的博客文章很好地解释了停车窗的原始意图。 必须重新创建子窗口的费用当然是最重要的。 但不是唯一的问题,某些类型的子窗口很难准确地重新创建。 TreeView是一个很好的例子,相当多的运行时状态与它相关联。 要准确地执行此操作,您必须记录每个节点的折叠状态。 这很痛苦,Winforms实际上并没有这样做。 当你重新分配,比如CheckBoxes或StateImageList属性时,你会发现这是错误的。

总而言之,这是一个很好的伎俩,但他们过分了。 当父窗口被重新创建时,子控件不仅(暂时)最终停留在停车窗口上,它还会在以下情况下移动到那里:

  • 您将其Parent属性设置为null
  • 您使用父级的Controls集合的Remove / At()方法
  • 您使用父级的Controls集合的Clear()方法

特别是最后两个子弹在典型的Winforms程序中几乎总是致命的 。 当程序员在运行时动态添加和删除控件时,往往会使用它们。 问题是,控件重新托管在停车窗口上,但程序员只是忘记了它们,失去了对控件的引用。 他们将永远生活在那里。 直到用户终止程序,因为它变成了慢速糖蜜,因为它创建了数千个窗口。 或者程序崩溃“错误创建窗口句柄”。 当程序创建10,000个窗口后,Windows出现阴沉时会发生这种情况。

相反, 需要调用控件的Dispose()方法。 在.NET中非常不寻常,调用Dispose()始终是可选的。 不在Control类的情况下,停车窗口保持对控件的引用,从而阻止终结器运行。

这篇文章由MS的Shawn Burke撰写: Windows Forms Parking Window 。

我们使用Windows Forms的目标之一就是尝试尽可能地消除Win32的奇怪之处。 其中一个主要的奇怪之处是窗口句柄(HWND)管理和生命周期。 我们当然不希望普通用户需要担心这些问题。 在大多数情况下,这很容易。 您只需收集所有状态,然后当您确实需要显示窗口时,按需创建,然后将状态从HWND而不是内部成员驱动。

嗯,这并不总是那么好用。 请参阅,Win32窗口的某些属性在创建窗口后无法更改。 例如,像边框的样式。 因此,要在创建窗口后允许用户更改边框样式,您需要重新创建句柄。 这意味着您不仅需要从现有状态中提取所有状态,还需要重新创建它并将其推回。好的,这不是太难。

但那些孩子呢? 哦,小提琴。 孩子们。

如果您正在修改边框的窗口有子项,则销毁其句柄也会破坏其所有子项的句柄。 然后你需要重新创建它们,这是非常昂贵的。 昂贵是坏事。

进入停车窗口。 停车窗口是我们解决这个问题的方法。 在某个地方你可以“停放”HWND,直到你有适合他们的父母。 把它想象为Window Handle Foster Care,但是看不见。

所以在手柄重新创建的情况下,我们会检查是否有孩子。 如果有的话,我们(如果需要的话)创建停车窗口,让子项为父,重新创建父项的句柄,然后将它们移回。 工作得很好,虽然管理停车窗口的生命周期确实导致一些问题…