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

[英]How do I know when all controls have loaded and displayed?


What is the real order of events in a Windows Forms application?

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

What I mean is, when I put code in the Form_Shown event, I expect that code only to run after the form has been Shown:

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

verb (used with object), showed, shown or showed, showing. 1. to cause or allow to be seen... - http://dictionary.reference.com/browse/shown

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

But the Form_Shown event is a little misleading. If I do some heavy stuff inside that event, it seems as though the code gets executed before the Form has finished been shown. Let's say that I have a MainMenu, a small Toolbar and a TextBox on a form.

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

I want to do some heavy stuff (nevermind threads and workers for now...), so the last event I can use I would think would be Form_Shown. So I put my heavy code in there, but when the Form begins to display, I end up waiting ~ 5 - 6 seconds for the Toolbar and stuff to display (which ends up happening after my heavy code does its thing.

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

Which leads me to believe that I'm subscribing to the wrong event. I don't want the Form_Shown event at all. What I really need is:

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

Form_WhenALLTheThingsHaveShownEventHandler event.

So, how can I know _when all the things (controls) have been fully loaded and displayed?

那么,当所有的东西(控件)都被完全加载和显示时,我怎么才能知道?

1 个解决方案

#1


The Shown event is in fact the last event related to initialization that is raised. However, note that the actual rendering (drawing on-screen) of UI objects in Windows (and on other platforms) is deferred. The creation of a UI object merely allocates all the necessary resources and "invalidates" the visual area of the object. The platform then later schedules the rendering event (in unmanaged Windows, this is WM_PAINT, in the Winforms API this would be the Paint event for a Control instance).

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

The rendering event cannot be dispatched until the UI object's thread is available, and if you have long-running code in the Shown event, that will keep the UI object's thread unavailable for the duration of your code. I.e. nothing gets drawn until your code completes.

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

There are other events that you could use to more reliably detect when things have "settled down". For example, the Application.Idle event tells you when the main application thread is about to enter the idle state. Alternatively, you could just subscribe to the form's Paint event. In either case, you would want to use BeginInvoke() to dispatch your long-running code, so that you don't block the handling of those events.

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


Now, all that said: you really should not be performing any long-running work in the UI thread, period. Using either of the above events doesn't solve the underlying problem; it simply delays the problem until after the initial rendering of your UI. The UI will still remain blocked while your long-running work is executing, and frankly the user may actually find it preferable for there to be no UI at all, than for there to be something that looks like they can interact with but which they can't (i.e. is unresponsive to their input).

现在,所有这一切:你真的不应该在UI线程,期间执行任何长期运行的工作。使用上述任何一个事件都无法解决潜在的问题;它只是将问题延迟到UI初始渲染之后。在您长时间运行的工作正在执行时,UI仍将保持阻塞状态,坦率地说,用户可能实际上发现它更好,因为根本没有用户界面,而不是那些看起来像他们可以互动的东西,但他们可以'(即对他们的输入没有反应)。

In the latest version of .NET, there are some very nice mechanisms available for shifting long-running work to background threads, so that the UI can remain responsive. See Task and the async and await keywords in C#. You could instead use the older BackgroundWorker object to accomplish the same, if you prefer.

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


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2015/05/13/9be3c96f1f98341d8c456fbf21a34b86.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com