Introduction

One of my pet peeves is forms that don't instantly appear. You see it all the time: the user clicks a button, then waits a few seconds until the expected UI appears. This is typically due to the newly-created form performing some time-consuming (blocking) task in its Load() event handler (or, in the non-.NET world, the WM_INITDIALOG message handler). Aside from being poor UI design (never leave the user wondering what's happening!), it can have some really undesirable consequences: a button-click doesn't have an immediate effect, users will tend to click the button again, which can result in the action being invoked twice.

Since my earliest Windows programming, I've always implemented "instant feedback" in my Forms (f/k/a "dialog boxes"). My technique has evolved as Windows API has evolved; I'll discuss my older techniques (which can still be used in .NET), and end up with my current implementation using .NET WinForms APIs.

The Goal

Create a simple, reliable mechanism for doing post-form-load processing which ensures that the form is "fully rendered" before the post-load processing commences. This means that all the controls in the form itself as well as all child controls (in the dialog template) have been drawn as the user would expect to see them.

Background

This is a pretty basic technique; novice WinForms coders should be able to implement it.

Complicating the issue is the asynchronous, not-totally-predictable nature of messages. When a window is created (and thus its children are created), the exact sequence of the various windows' messages varies from instance to instance. Certainly, each window's messages occur in the same sequence every time, but the sequence of the parent/child messages is unpredictable, creating a race condition. The most unfortunate result of this being that sometimes a dialog will render properly, sometimes it won't. Removing this uncertainty - ensuring predictability - is a big part of this solution.

Finally, it's very important to perform your blocking processing after the form and all children are fully rendered. Blocking the UI thread (and message queue) mid-render, results in some pretty partial ugly UI that looks like your app crashed!:

Notice how the form's frame and unclipped client area have rendered but certain child controls' client areas still show the UI "below" the form. Also notice how the listbox has rendered but the other controls (GroupBoxes, ComboBoxes) have not (I haven't investigated why that is).

Here's how it should look fully rendered:

Solution: Before .NET

(If you wrote Windows code before .NET - with or without MFC - this should look familiar.)

Here's a simplified sequence of the messages generated upon window creation:

The theory here is essentially the same: Set a quick (50ms) timer in the initial activation. The WM_TIMER message occurs asynchronously and with some extra delay. The timer is immediately killed (we only wanted the first timer message), then the derived class' DoPostLoadProcessing() is called. (Yeah, I know that timers < 55ms are useless on a PC.)

Both techniques work pretty well, and could still be used in .NET, though they're messy.

Solution: Doing it in .NET

The basics

.NET's addition of the Shown() event simplifies things greatly. Now, in theory, all you'd need to do is handle the Shown() event and do your processing there:

Simple, right? Well, almost. It turns out that the Shown() event gets fired before all the form's child controls have fully rendered, so you still have the race condition. My solution to that is to call Application.DoEvents() to clear out the message queue before doing any additional post-processing:

A more complete solution

The problem with the basic solution above is that you must remember to call Application.DoEvents() in each form's Shown() event handler. While this is admittedly a minor nuisance, I've chosen to take the solution one step further by implementing a base dialog class that handles the Shown() event, calls DoEvents(), then invokes an event of its own:

(I named the event LoadCompleted so that it would appear immediately after the Load event in the events pane, making it easier to find.)

With that, you can do all your long-duration stuff in LoadCompleted() and be confident that the basic UI will be fully rendered while the user waits. Of course, you should still follow good UI practices such as showing a WaitCursor, maybe disabling the controls until they're usable (a useful visual cue to the user), and perhaps even showing a progressbar for really long waits (e.g.: show a marquee progressbar during a SQL call that takes 5+ seconds).

Demo project

The attached VS2008/C# project demonstrates the behavior and the solution. It implements a form with four buttons:

All four buttons do the same thing, which is pop up a child dialog containing:

A listbox that gets populated with 50K items. This population blocks the UI thread for a couple of seconds, which allows the app to demonstrate the solutions to the problem.

A few other controls, principally ComboBoxes. For whatever reason, ComboBoxes are particularly prone to incomplete rendering due to blocking code.

Each child form sets the WaitCursor in its Load() event as a visual feedback that things are happening.

However, each button causes a different form-loading behavior:

Do processing in Load event - the listbox is loaded in the form's Load() event handler, resulting in the form not appearing until the listbox is fully loaded (bad).

Open Form Without DoEvents - the listbox is loaded in the form's Shown() event handler, but Application.DoEvents() is not called, resulting in the form appearing partially rendered until listbox-load completes (very bad).

Open Form *with* DoEvents - the listbox is loaded in the form's Shown() event handler andApplication.DoEvents()is called, resulting in the form appearing fully rendered until listbox-load completes (good!!!).

Open Form derived from BaseForm - Same as Open Form *with* DoEvents, but implemented using a base class and custom event.

Conclusion

Like so many things in Windows (and in life!), the solution to this problem is pretty simple, but figuring it out takes a bit of trial and error. I hope that my solution outlined above saves you some time and helps you create more responsive UIs.

Hey!! this is a nice piece of work. Thank you very much for sharing these tricks.

I've implented this succesfully on my applications but I did find some curious problem that seems to appear randomly: On some forms the OnShown event won't be raised and I was not able to figure out why, this is most strange because it works fine on most cases and I use a class that inherits the Form class and handles the event for me, so there should be no way for me to mess up with the event handling.

Did anybody experience this problem?? Were you able to fix it?? I'd be most thankful if anyone could offer a piece of advise so I can solve this.

Historically, ListBoxes have been limited to 64k (0xFFFF) items. This was originally a short-int (signed 16 bit; <=32k, and anything over 32k rolled over to a negative number and caused bad things), then sometime around Win98 they fixed this to be a WORD (unsigned 16 bit) with the current limit of 64k.

I'd imagine that MSFT has never increased the limit beyond 64k because, beyond several hundred items, it's the wrong tool for the job and results in crapppy UI.

I once had a requirement for a listbox that needed to contain the Lotus Notes email address for *every* USPS employee. It was ridiculous, but that's how the USPS's IT manager wanted it (the guy was a mid-level, power-mad douche), so that's how it had to be. They had something like 300k addresses and had to be fetched via a slow-ish IP-based API (this was around 1995) that took about 6 minutes to pull all 300k items. So the challenge was to (a) list >32k items in the listbox, and (b) have responsive UI when the user did type-ahead (ie. when the user typed 'n' to start pulling at 'n', skipping a-m).
My solution (in non-MFC C++) was a custom ListBox with my own custom, discontinuous Items array. It worked really well, but was a ton of custom code. dotNET has made this much easier, though I've only done it for ListView not ListBox.
I've not searched, but I'm sure that there's an example out there for a >64k ListBox.

> DoEvents is so VB6
So what? Snobbery leads to a LOT of bad decisions... don't be too proud to use any/all tools available to you. I've been using the equivalent of DoEvents() for 20+ years; it has its place.

I experimented with BackgroundWorker as well and found that it's also prone to the race condition.

How does one instantiate and display a UserControl in this fashion? (I've never done it).
Can you provide a code snippet?

Also, what's the rationale for doing UserControls instead of Forms? Not challenging your design.. it's just that I've never done a UC in place of a Form so I'd like to learn why one would consider doing it that way.

My main form has a tab control for its main work space. A menu click instantiates a user control object and adds it to a new tab page's controls collection. The painting of the user control is usually very choppy looking. I've played with SuspendLayout, setting the user control to visible=false until it finishes loading, etc. The user control's Load event doesn't fire until after it is painted. Nothing seems to work.

Hi. My name is Ariel and I'm from Argentina.
My question is what does it happen when the controls get their data from a Database ?
We are using ORM Wilson. We populate combos and listboxes with entities generated from data in a SQL Server Database.
Can this approach work with this in mind ?

where 'listView1' is a custom control derived from System.Windows.Forms.ListView.

listView1.Fill does the SQL and loads itself, all the while showing a ProgressBar.
The form (FormThatDisplaysSqlData) pops up immediately and fully rendered, then the progressbar gives the user something to watch during the SQL/load.

I've fielded this question many times and I am always surprised how few people are aware of the Shown event -- it's like it flies under the radar, even for some seasoned developers. I'm guessing that the MS tutorials mostly (or totally) ignore or omit it.

Like many people who do WinForms I'm always hesitant to use Application.DoEvents() because of its "catch-all" effect, but I think at teh top of the Shown() event handler may be one of the safest places to use it simply because the user has not been given a chance to interract with the form yet and register some clicks and what-not. That leaves programmatically-induced lingering events to be completed (i.e. a list control's Selected[Whatever] event) and those can be managed and mitigated by the developer.

Anyhow, thanks for the well-written peice. I'm bookmarking this one so I can include the link the next time this question pops up.

While I'm also wary of Application.DoEvents(), I do feel that this is one of those places where it's entirely appropriate, for the reasons you state.

If a developer was really concerned about restricting user actions until the form was truly ready for use, you could disable the controls in the form designer then "manually" enable them at the end of LoadCompleted().

5 from me. A complete implementation would include a Visual Studio template that allowed you to directly add a form derived from the base class.

.45 ACP - because shooting twice is just silly-----"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997-----"The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001

I hadn't thought of using a template - I've been doing it by adding Inherited Forms based on BaseForm, wherein I manually add the handler for LoadCompleted. Using a template would automate that and save a few clicks.

This will allow forms that derive from BaseForm to override the OnLoadCompleted method and handle the situation, rather than hooking up to an event. This is desired since derived implementations can deal with the situation directly, rather than being deferred through an event, as events are typically used for external signalling of events.

Also, following the pattern of "handle the situation yourself", you should override the OnShown method in your BaseForm, again instead of hooking up to the Shown event:

This is handy way to speed up the showing of a form, but I think if you seriously have 25 seconds of preprocessing to do before your from is usable then a small dialog should open with an animation or progressbar informing when then next form will be ready.

At any point a dialog that looks like its ready to use that isn't, is trouble. The doevents call means that all the controls on that "shown but not ready form" are going to be clicked like crazy by anxious users and the form will stop responding.

For simple 2-5 second delays, this could really make a program seem more responsive. But for long 10+ second delays, this could potentially make the user think that the program has crashed because they can see it but not use it.

disabling the button and changing its text to "working..." would show the user that the button was clicked and that something is happening while plus keeping it from being pushed again.

Not to take any credit away from you, as this is a well researched and written article and I do appreciate you sharing your knowledge! I see this as not a catch all solution but one to be considered when appropriate.

> 25 seconds of preprocessing
What I typically do is show the new UI immediately, then pop a small, modal window on top of that which contains a progressbar (Continuous or Marquee, depending upon if you can compute the duration) and a message saying something like "Loading your information, please be patient".

> "shown but not ready form" / for long 10+ second delays
I totally agree. If there's a long (maybe >2 second?) delay, you gotta show some additional, preferably animated, UI to give the user warm fuzzies (such as the popup I mention above). Showing the new yet unresponsive UI solves nothing.

I had actually added the "Shown" event in one form that took several seconds for a database call to load a listview. I noticed the display problem mentioned in the article. After reading this very helpful article - went back and added the DoEvents to my Shown event and also added the following code:<code>Application.DoEvents();string sSave = this.Text;this.Text = (sSave + " - Loading Settings...");this.Enabled = false;[My code reading settings/database/etc.]this.Enabled = true;this.Text = sSave;</code&gt;(Actually did it in VB and converted to C# for this reply) It works great - the form displays quickly and it is obvious that processing is going on!Thanks DLChambers for teaching an old dog a new trick (been doing VB/C++ since version 2).

I guess Application.DoEvents could work, but I'm unaware of any particular limits as to what sort of events it might try to do. I wish Microsoft would implement a version of Application.DoEvents that would handle paint and other such events without allowing through client-area mouse-clicks, keystrokes, etc.

BTW, I tend to think that often the right approach to handling a UI is to have a thread for each window that does stuff for that window, and then avoid putting any blocking tasks in the UI thread. Simply use a delegate queue with a ManualResetEvent or other means to have the UI thread perform tasks on the other thread. In that scenario, the time required to handle the form loading would be a non-issue from a UI-thread perspective.

Yes, I've used BeginInvoke as well, but have found that to be non-deterministic. Same with the separate thread.
I'm not saying that my method is the only way to do it, or the best way. I simply offer it as a simple mechanism that has worked well for me. The whole start-a-thread thing strikes me as a lot of extra work when the built-in Shown() event gets you most of the way there.
What I really wish is that MS would offer an event that fired when the UI was really, truly complete so that we wouldn't have to create all these hacks to do something that you'd expect would be there in the first place. Shown() shouldn't require me to call Application.DoEvents!!

Agreed that the WaitCursor should take care of the "did the app see my click?" issue, but remember that simply switching to WaitCursor doesn't disable the UI, so they can still click stuff. And we've all clicked something, received the WaitCursor, then... hang.

I view it as more of a "style" thing... when you (as a user) click a button (or menu item, or...), would you prefer instantly appearing UI or a delayed appearance of UI? (Assuming both methods show the WaitCursor, and both methods take the same amount of time until the UI is fully populated and/or usable). I find that users are happier (or more forgiving) when they instantly see the new UI, even if that new UI isn't yet usable. As long as you're going to be popping some new UI, why not pop it immediately?