Keeping your UI Responsive and the Dangers of Application.DoEvents

What’s the difference between Application.Run and Application.DoEvents? 

Application.Run continually processes window messages for your application, raising events as necessary.  Application.DoEvents processes all the window messages in the queue until it has run out of messages, then returns.

Making your CPU work too hard

Given this definition, one could conceivably suggest that Application.Run could be replaced with:

while(!quit) {

Unfortunately, when you run the application, switching over to the while loop spikes the CPU to 100% utilization. 

Why? Under the covers, DoEvents “peeks” message until it sees no more on the queue, then stops.  PeekMessage returns immediately (after doing its administrative work processing sent messages, etc) – therefore not yielding to other threads that may have work to do.  On the other hand GetMessage/WaitMessage block waiting for the new message, allowing other processes/threads get their work done. 

Adding new codepaths that might be unhandled

Let’s take the example where you add a whole bunch of items to your listbox in a button click event.  It takes forever, and its not painting.  So you add an Application.DoEvents to force a refresh.  When you’re done you set the text of the first control on the form to “finished”.

       private void button1_Click(object sender, System.EventArgs e) {
            for (int i = 0; i < 10000; i++) {
                Application.DoEvents();  // <-- Calling DoEvents processes other events that may occur
            this.Controls[0].Text = "Done";


What happens if the user clicks the close button?  Ooops!  IndexOutOfRangeException!  Clicking on the close box has invoked the form’s Dispose method, which has cleared the control collection.  What's worse is that clicking close on the form didn't stop the list box processing from finishing up - while the form was no longer visible, this handler was merrily keeping the application alive.

Why wouldn’t this normally happen?  The action of the user pressing the close button would not be processed until you’ve returned from the handler for the button click.

The codepath when it works:

    Process mouse up on button
          Fire ButtonClick event
              Add bunch of items to listbox
              Update the first control on the form
    Process mouse up on close box
          Dispose the form

The explosion after sprinkling in Application.DoEvents:

    Process mouse up on button
          Fire ButtonClick event
              Add some items to listbox
              Call Application.DoEvents to make it look more responsive
                   Process mouse up on close box
                       Dispose the form
              Add remaining items to listbox 
              Update the first control on the form  -- BOOM!  Controls collection has been cleared!

This is just one example of codepath gone bad, there’s plenty of others – say the user clicked the button a second time – the button click event would be called again while you’re still processing the first!

                 bool inButtonClick = false;
        private void button1_Click(object sender, System.EventArgs e) {
            if (inButtonClick) {
                MessageBox.Show("Being called when I'm already in here!!!");
            inButtonClick = true;
            for (int i = 0; i < 10000000; i++) {
                Application.DoEvents();  // <-- this call here allows the second click to process
            inButtonClick = false;


Ugh, I have a DoEvents, now how do I fix it?

So we’ve established there’s a real need for processing events, but we’ve established that calling it can cause more trouble than it solves.  What are some ways to fix it?

Ask yourself, why are you calling Application.DoEvents?

Need painting to happen right now.

Problem: You’ve written a custom control, you’ve changed some state, and it’s not painting fast enough for you.  The most common example of this is changing the look of the button when the mouse is released.  You change some flag that says it shouldn’t look “pressed” anymore, and have called Invalidate() but it’s not painting because someone has hooked up a long running click handler – the paint wont be processed until the click is done.  So you think, I’ll just call Application.DoEvents to process everything that needs to happen before firing a click event.  In actuality, all you need to happen right now is the paint event. 

Solution:  Use invalidate to invalidate the area that needs repainting, and if you just cant wait for the paint to happen, follow your call to Invalidate() with Update().  This will force a synchronous paint.

Want to do work after we’ve processed all the current events.

Problem:  You’ve created a form, and you want to do work after it’s been shown.  You figure, create the Form, show it, clear the events in the queue, then finish your processing.  Something like:
    Form1 f = new Form1();

Solution:  See if there is already an event that corresponds to when you want to do your work. In Whidbey, you can use the Shown event for form to do exactly this.  For the WebBrowser, use the DocumentComplete event.

If there is no event that matches up, you can use BeginInvoke (yes, even on the same thread!)  BeginInvoke is essentially a PostMessage, under the covers it adds on to the end of the list of things the app needs to do. 

Why is this the same as Application.DoEvents()?  You’re clearing out the list, then doing more work.  This just eliminates the step of clearing out the list yourself.  If something has happened, like the user has clicked the close box, windows will automatically clear out the rest of the work in its message queue, so you don’t have to worry about pending BeginInvokes after the control has gone away.

Have a whole bunch of UI to update, need to make the UI responsive whilst adding new items
Problem:  You have a whole bunch of data you want to put into some grid/listbox/listview/treeview, the act of which is making your UI choke.

Solution:  Try to suspend processing of newly added items.  Read up the documentation for the UI, it could be that it supports methods that help you add in bulk.  In particular, look for methods like as BeginUpdate/EndUpdate, SuspendLayout/ResumeLayout and AddRange. 

Consider VirtualMode if offered. Some controls offer Virtual mode (I believe ListView and DataGridView offer these in Whidbey) – the idea here is that rather than having rows/items for everything, only have rows/items for the data that the user is looking at right now.

Consider using the BackgroundWorker to fetch results, updating your UI in chunks.  If the processing work can be done on a background thread, use the new BackgroundWorker component to help offload the work to another thread.  Note you cannot create controls/items on the background thread and use them on the UI thread – the only work that can really be done here is fetching data/doing some other kind of data processing. 

Consider creating a ForegroundWorker: If it must be done on the foreground thread, consider using a similar technique to the background worker: chunk up your data into manageable pieces, then use a System.Windows.Forms.Timer to add in new results.   The nice thing here is that the WM_TIMER message is a low priority message, so the UI will have a chance to paint itself.

When is it OK to add an Application.DoEvents?
There are some workarounds you’ll find in MSDN that suggest using Application.DoEvents to clear up one problem or another.  Usually the crux behind these problems is that no one is pumping messages at the time (no one has called Application.Run).  In this case, because no one else is pumping messages, you won’t get the re-entrant code problems.

More information
ListView virtual mode,vs.80).aspx
DataGridView virtual mode,vs.80).aspx
Background Worker



Comments (21)
  1. zzz says:

    Too bad the DoEvents docs doesn’t mention anything like: This method is mostly used for workaround purposes. Use method/pattern X instead.

    There is a sample that suggests example use of "Call Application.DoEvents to force a repaint". I guess that’s workaround when you need to "force". Isn’t having such samples suggest that DoEvents is the correct way of doing x instead of being a workaround.

    It would be good if such workaround methods had a clear note like this blog entry that if you need to use it you may have a bad design or whatever.

  2. Daniel Moth says:

    Blog link of the week 31

  3. If I need to create a window (not necessarily a Form, could be a NativeWindow) in a separate thread, it would need to run its own message loop — something like the old PeekMessage/TranslateMessage/DispatchMessage loop.

    Looks like calling Application.Run() from that thread is the way to do that, but are there any special considerations when calling Application.Run() from another thread (other that the main one that already called it)?

    Would it be a good idea to do it at all?

  4. Jankrod says:

    So Maybe you can help me. My current use for a possible DoEvent is to keep the application resizable, movable, and minimize-able when doing heavy processing. DoEvents can do this for me, but I don’t want any of the elements on the screen to be active. With the DoEvent you can minimize, but you can also click on other things and that mess up stuff when I’m trying to do calculations.

    What I really want is a DoMinimizeAndMaximizeEvent, so some way to call the events directly, but not all of them. I can check with GetQueueStatus, if one of those are in the queue but I cant restrict the other event from going into the queue.

  5. Another great blog entry by Jessica Fosler: Keeping your UI Responsive and the Dangers of Application.DoEvents…

  6. ShadowChaser says:

    I agree completely about Application.DoEvents. Don’t forget that it also adds objects to the garbage collector each time it is run, creating memory & performance issues when placed in a tight loop.

    That said, developers are really backed against a wall when developing WinForms apps that need code to "hook" into the main application loop, like games. There are no easy solutions outside of nasty hacks or building from the ground up using Interop

  7. jfoscoding says:

    zzz – you have a great point RE the docs, I’ll file a bug against the documentation. You’re also welcome to file a bug using product feedback:

  8. jfoscoding says:


    I assume you’re thinking about doing some message passing or something?

    Running the message loop on the second thread in and of itself wont be a problem, I think stopping it will. If you dont stop the message loop on the second thread, the program wont exit:

    Try runnning this under the debugger

    Thread t = new Thread(new ThreadStart(NewThread));




    private void NewThread() {



    If you dont kill the message pump on the second thread, you’ll notice in the debugger that while the form closes, the application doesnt exit.

    One way you could manage the lifetime of the message pump on the second thread is to use an ApplicationContext:


    private void NewThread() {

    Application.Run(new BackgroundThreadApplicationContext(this));


    public class BackgroundThreadApplicationContext : ApplicationContext {

    public BackgroundThreadApplicationContext(Form mainForm) {

    if (mainForm != null) {

    mainForm.Closing +=new CancelEventHandler(mainForm_Closing);



    private void mainForm_Closing(object sender, CancelEventArgs e) {

    Form mainForm = sender as Form;

    if (mainForm != null) {

    mainForm.Closing -=new CancelEventHandler(mainForm_Closing);





    More details of how to use ApplicationContext are up at

  9. jfoscoding says:

    Jankrod –

    I dont know if it’s possible, but I’d try moving the "heavy processing" to a background thread and update your UI in chunks. You may also want to Thread.Sleep the "heavy processing" thread to yield some time back to your UI thread so that it has the opportunity to be a little more responsive to users.

    In Whidbey the BackgroundWorker API helps make this easy, but it’s just a fluffy layer on what was already out there in 1.0/1.1 – just use Invoke and/or BeginInvoke to communicate back with the main UI.

    An example is here

  10. jfoscoding says:


    Regarding the games thing, you might be right, although given a specific example there might be a workaround.

    Regarding hooking into the message loop, any class can implement IMessageFilter and respond to a particular window message.

    See all about handles in windows forms as it may have some more tips for you here..

  11. Link Blog says:

    jfo’s coding : Keeping your UI Responsive and the Dangers of Application.DoEvents

    What&amp;rsquo;s the difference…

  12. Thanks Jessica,

    Actually I had the ApplicationContext in mind but I was in a short intellectual coma when I was writing my question.

    Here’s what I really wanted to ask: assuming that I do pass an ApplicationContext to a second thread (see the code below), are there any threading or other issues if both threads wait for the same (main) Form to close (within their respective Application.Run calls)?


    <main thread>

    static void Main()


    MyMainForm mainForm = new MyMainForm();

    ApplicationContext applicationContext = new ApplicationContext(mainForm);

    // Create second thread

    // Pass applicationContext to that thread, or somehow made it accessible from there

    Application.Run(); // or Application.Run(mainForm), I guess it doesn’t make a difference (?)


    <second thread>

    // Somewhere in the code, wait for the main form to close

    Application.Run(applicationContext); // same app context created in main()

  13. jfoscoding says:

    Vladimir: I would hesitate to pass the same application context to a different thread – while I dont know of any issues offhand, it was not designed to be thread-safe: e.g. no one’s taking locks at appropriate times.

    It’s probably safer to roll your own application context here for the second thread.

  14. Link Blog says:

    jfo’s coding : Keeping your UI Responsive and the Dangers of Application.DoEvents

    What’s the difference…

  15. jfo's coding says:

    There were a lot of good comments/questions about keeping your UI responsive, if you’re interested in…

  16. jfo's coding says:

    Custom PaintingPainting best practices ComboBox OwnerDrawLayoutDock layout/Using the Splitter control…

  17. When reading someone else’s blog (even when searching for the answer to a specific problem) occasionally…

  18. While doing the Vista Test Pass, I noticed a lot of timing and synchronization issues in the tests, and…

Comments are closed.

Skip to main content