Why DoEvents is Evil

From HashVB
Revision as of 21:57, 13 October 2005 by IQJunkie (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Alot of code out there relies on the DoEvents statement, or even advertises the use of it. DoEvents can be useful in some cases, but in general it should not be used !

A call to DoEvents blocks until all the WM_MESSAGES in the message queue are processed, WM_MESSAGES are used by Windows (all versions of it) to notify an application of an "event". (Mouse or keyboard activity, timers, etc...)

While the DoEvents statement is blocking the normal execution flow of the application, the GUI remains responsive however, this means that another block of code can be entered that also has a DoEvents statement in it, or even that the same block of code can be entered again.

There are now two DoEvents calls blocking, if another DoEvents statement is encountered it will block again... this can cause stack overflow easily.

The following code demonstrates this behavior...

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  
       For n As Integer = 1 To 10000
           Button1.Text = n.ToString
           Application.DoEvents()
       Next
 
 End Sub

When you click that button, the loop will be entered, and its progress shown on the button itself. The UI is responsive, meaning you can click that same button again, the first loop will now be paused on the DoEvents statement, until the second loop terminates. Click it again to start a thirth loop, and so on...

Next to risking stack overflow exceptions, it is almost impossible to predict the flow of your application, making debugging very painful.

If you have a process that will take a long time and you have to use DoEvents, you should either disable any User Interface that can "interfere" with the process or set a flag to say it is working. You can then check this flag when they try and start it again or shut the program down. This is a simple Mutex as in it can only be executing once at any time.

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      
       Static Overlapped As Boolean = False 
 
       If Overlapped = False Then
          Overlapped = True
          For n As Integer = 1 To 10000
              Button1.Text = n.ToString
              Application.DoEvents()
          Next
          Overlapped = False
       End If
 
 End Sub