How do I know when all the controls are loaded and displayed?
What is the real order of events in a Windows Forms application?
What I mean is, when I put code in an event Form_Shown
, I expect the code to only run after the form has been shown:
verb (used with object) shown, shown or shown, showing. 1.call or let see ... - http://dictionary.reference.com/browse/shown
But the event is a Form_Shown
little misleading. If I do some heavy stuff inside this event, it seems like the code runs before it finishes Form
. Let's say I have MainMenu
small Toolbar
and a TextBox
in shape.
I want to do some heavy stuff (no threads and workers now ...) so the last event I can use I think would be Form_Shown
. So I put my heavy code there, but when the form starts to display, I end up waiting ~ 5-6 seconds for Toolbar
and material to display (which ends up when my heavy code does its thing.
This makes me think that I am subscribing to the wrong event. I don't need an event Form_Shown
at all. I really need:
Form_WhenALLTheThingsHaveShownEventHandler
event.
So how can I know when all things (controls) have been fully loaded and displayed?
source to share
The event Shown
is actually the last initialization event that is raised. Note, however, that the actual rendering (drawing on the screen) of UI objects on Windows (and other platforms) is deferred. The creation of the UI object simply allocates all the necessary resources and "cancels" the visual area of ββthe object. The framework then schedules a render event (on unmanaged Windows this WM_PAINT
, on the Winforms API this would be an event Paint
for the instance Control
).
A render event cannot be dispatched until the UI object stream is available, and if you have long code in the event Shown
that will keep the UI object stream unavailable for the duration of your code. That is, nothing is drawn until the code completes.
There are other events you could use to more reliably detect when things have calmed down. For example, an event Application.Idle
tells you when the main application thread is about to enter a pending state. Alternatively, you can simply subscribe to the form Paint
. Anyway, you would like to use BeginInvoke()
to dispatch your long code so that you don't block the handling of these events.
Now all that said, you really shouldn't be doing any lengthy work on the UI thread, period. Using any of the above events does not solve the underlying problem; it just delays the issue until your UI starts rendering. The UI will still remain locked while your lengthy work is being done, and in all honesty, the user may actually find it preferable to have no interface at all than to have something that looks like an interaction but they can't (i.e. does not respond to their input).
The latest version of .NET has very good mechanisms for pushing long running work to background threads so that the UI can remain responsive. Cm. Task
, And keywords async
, andawait
C #. You could use an older object instead BackgroundWorker
to do the same if you like.
source to share