如何知道所有控件何时加载并显示?

时间:2015-05-13 04:34:23

标签: c# .net winforms

Windows窗体应用程序中事件的真实顺序是什么?

我的意思是,当我将代码放入Form_Shown事件时,我希望代码只能在表单显示之后运行:

  

动词(与对象一起使用),显示,显示或显示。 1.引起   或者允许被看到...... - http://dictionary.reference.com/browse/shown

Form_Shown事件有点误导。如果我在该事件中做了一些繁重的事情,似乎代码在之前执行 Form已经显示已完成。假设我在表单上有MainMenu,小ToolbarTextBox

我想做一些沉重的事情(现在没关系线程和工人......),所以我可以使用的最后一个事件我认为是Form_Shown。所以我把沉重的代码放在那里,但是当表格开始显示时,我最终等待〜{ - 6}秒Toolbar和东西显示(最终发生 之后)我的重型代码可以做到这一点。

这让我相信我正在订阅错误的事件。我根本不想要Form_Shown事件。我真正需要的是:

Form_WhenALLTheThingsHaveShownEventHandler事件。

那么,当所有事物(控件)都已完全加载并显示时,我怎么知道?

1 个答案:

答案 0 :(得分:2)

Shown事件实际上是与引发的初始化相关的最后一个事件。但请注意,Windows(以及其他平台)上的UI对象的实际呈现(绘制在屏幕上)是延迟的。 UI对象的创建仅仅分配了所有必要的资源,并且"无效"物体的视觉区域。然后,平台会调度渲染事件(在非托管Windows中,这是WM_PAINT,在Winforms API中,这将是Paint实例的Control事件。

在UI对象的线程可用之前,无法调度呈现事件,如果在Shown事件中有长时间运行的代码,则会使UI对象的线程不可用在你的代码的持续时间。即在你的代码完成之前,什么都不会被绘制出来。

您可以使用其他事件来更可靠地检测事情何时已经解决了#34;。例如,Application.Idle事件告诉您主应用程序线程何时进入空闲状态。或者,您可以订阅表单的Paint事件。在任何一种情况下,您都希望使用BeginInvoke()来分发长时间运行的代码,这样您就不会阻止这些事件的处理。


现在,所有这一切:你真的不应该在UI线程,期间执行任何长期运行的工作。使用上述任何一个事件都无法解决潜在的问题;它只是将问题延迟到UI初始渲染之后。在长时间运行的工作正在执行时,用户界面仍然会被阻止,坦率地说,用户实际上可能会觉得最好不要使用任何用户界面,而不是那些看起来像是可以互动的东西,但他们可以和#39; t(即对他们的输入没有反应)。

在最新版本的.NET中,有一些非常好的机制可用于将长时间运行的工作转移到后台线程,以便UI可以保持响应。请参阅C#中的Taskthe async and await keywords。如果您愿意,也可以使用较旧的BackgroundWorker对象来完成相同的操作。