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?

+3


source to share


1 answer


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.

+2


source







All Articles