DoEvents in many cases will do more harm than good.
I create a subroutine called Do_Events(). It checks the current time and compares it with a global time value that I set ever x seconds. Then, after that much time has gone by it does a DoEvents()
I generally set the time to 3 seconds.
Sub Process_Globals
Private DoEvent_Seconds As Int = 3
Private EventCounter As Long = 0
end sub
Sub Do_Events(WhichDoEvent As Int)
Dim Now As Long
Dim Difference As Long
Dim NumSecs As Long
Now = DateTime.Now
Difference = Now - EventCounter
NumSecs = DoEvent_Seconds * DateTime.TicksPerSecond
If Difference > NumSecs Then
Log("DoEvent #" & WhichDoEvent)
EventCounter = Now
DoEvents
EndIf
End Sub
Then, to use it I just put a Do_Events( 1 ) before my first End Sub, a Do_Events( 2 ) at the end of the second, etc.
I also put one just before each 'Loop' statement. You can use Do_Events( 1001 ), Do_Events ( 1002 ) for those... that way you'll know the difference between DoEvents in a Loop or DoEvents from a subroutine.
That way you can put as many of them as you want into your code... yet they only trigger every 'DoEvent_Seconds ' seconds.
Also, you can see which DoEvents are occurring by the Log. Some may trigger regularly, others might never hardly trigger.
Don't put any Do_Events( ) into subroutines that can't possibly cause the problem (ones that can't be inside a loop of any kind such as a Button Click, etc).
(If you want DoEvents to be triggered that are less than a second... don't do the multiplication x 1000 and just compare it as milliseconds. I just like putting 1 for seconds rather than 1000 for ms).