Introduction

This example illustrates the correct use of Application.DoEvents() in order to allow a window to repaint (or handle the
desired messages) while its thread is busy doing heavy processing.

Background

Calling Application.DoEvents() used to be the easy way of making your window repaint, but this
method is really dangerous, because it not only allows the window to repaint, but also
processes all the events the user issues to the window, such as button presses etc.,
which can lead to unwanted behavior in the form
of function reentrancy or unwanted event handler execution, leading to
malfunction and possible crashes.

Using the code

The code comes in the form of a utility class with a function called DoPaintEvents().

The solution is based on the use of a IMessageFilter that decides which messages will do execution and which don’t, and it’s pretty straightforward and easy to
modify to fit other user needs.

Comments and Discussions

I used and liked your implementation to force painting. It took me a couple of days to find out that this is responsible for some strange behaviors in our software. A WinForms button stayed pushed while mouse is released. WPF controls are not painted if properties changed. Now I know that important messages like MouseUp and WPF registrations was swallowed by this DoPaint implementation.

Application.DoEvents without message filter is dangerous because you don't know what you do. Application.DoEvents with message filter is dangerous because you don't know what you miss to do.

Block all messages can cause strange behaviour. I've just encountered a problem by using the technique described above with a BackgroundWorker component. It was blocking a custom Windows message (in the range 0xC000 through 0xFFFF registered with RegisterWindowMessage) and this was preventing ProgressChanged and RunWorkerCompleted events to be raised on the BackgroundWorker.