Windows窗体应用程序中事件的真实顺序是什么?
我的意思是,当我将代码放入Form_Shown
事件时,我希望代码只能在表单显示之后运行:
动词(与对象一起使用),显示,显示或显示。 1.引起 或者允许被看到...... - http://dictionary.reference.com/browse/shown
但Form_Shown
事件有点误导。如果我在该事件中做了一些繁重的事情,似乎代码在之前执行 Form
已经显示已完成。假设我在表单上有MainMenu
,小Toolbar
和TextBox
。
我想做一些沉重的事情(现在没关系线程和工人......),所以我可以使用的最后一个事件我认为是Form_Shown
。所以我把沉重的代码放在那里,但是当表格开始显示时,我最终等待〜{ - 6}秒Toolbar
和东西显示(最终发生 之后)我的重型代码可以做到这一点。
这让我相信我正在订阅错误的事件。我根本不想要Form_Shown
事件。我真正需要的是:
Form_WhenALLTheThingsHaveShownEventHandler
事件。
那么,当所有事物(控件)都已完全加载并显示时,我怎么知道?
答案 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#中的Task
和the async
and await
keywords。如果您愿意,也可以使用较旧的BackgroundWorker
对象来完成相同的操作。