Difference between revisions of "Why DoEvents is Evil"
(6 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
Alot of code out there relies on the DoEvents statement, or even advertises the use of it. | Alot of code out there relies on the DoEvents statement, or even advertises the use of it. | ||
− | DoEvents can be useful in some cases, | + | 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, | A call to DoEvents blocks until all the WM_MESSAGES in the message queue are processed, | ||
Line 13: | Line 13: | ||
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click | Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click | ||
− | + | ||
For n As Integer = 1 To 10000 | For n As Integer = 1 To 10000 | ||
Button1.Text = n.ToString | Button1.Text = n.ToString | ||
Application.DoEvents() | Application.DoEvents() | ||
Next | Next | ||
− | + | ||
End Sub | End Sub | ||
Line 26: | Line 26: | ||
Next to risking stack overflow exceptions, it is almost impossible to predict the flow of your application, making debugging very painful. | 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 |
Latest revision as of 21:57, 13 October 2005
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