Tag Archives: getinputstate

Using DoEvents() in Visual Basic and .NET the Right way!

Click Star to Rate Post
1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.75 out of 5)
 

The DoEvents() method is well known and available in VB 6.0 and VB.NET. Its often used in longer running, processor intensive code. It tells Windows to process the messages in the program’s message queue. That can help keep your program from appearing frozen and allows user interaction while the CPU is still busy executing the high usage code.

(In VB 6.0 and Older DoEvents() is a Function | In .NET and Newer its a Subroutine)

Unfortunately there is a tradeoff when using DoEvents. That tradeoff is ‘Performance’. The more you call DoEvents, the more CPU cycles are taken away from your intensive code to process the message queue. Thankfully, there is a way to help offset much of the performance loss and still allow your program to be responsive. That’s by using the GetInputState() function in the User32.dll library.

[Note:

Most of the code in this article is from an example I made at www.vbcodesource.com.

It runs 3 different scenarios with benchmark data for each of them.

Scenario One: is executing a CPU intensive loop Without using DoEvents().

Scenario Two: is executing the loop using DoEvents() with the GetInputState() API call.

Scenario Three: is executing the loop using Only the DoEvents() method.

End Note]

Windows API to the Rescue

What’s nice about the GetInputState() function is you can use it to First Check if there are any messages in the calling thread’s queue that is waiting to be processed. Below is the declare for that function…

Visual Basic 6.0
'
'This call will see whether or not there are any messages waiting
'to be executed in the calling thread.

    Private Declare Function GetInputState Lib "user32" () As Long

Visual Basic.NET
'
'This call will see whether or not there are any messages waiting
'to be executed in the calling thread.
    Private Declare Function GetInputState Lib "user32" () As Int32

—————————————————

This function is very simple to use. Just simply get its return value to see if any mouse and/or keyboard messages needs processed…

'
'You save ALOT of time by using the GetInputState api call to check
'whether any messages needs to be processed first. The DoEvents()
'method is ONLY fired when there ARE messages that needs to be processed,
'thus really increasing the performance of your application.

'If it returns 0, then there are NO keyboard or mouse messages queued in the thread.

  If Not GetInputState = 0 Then Application.DoEvents()

—————————

Performance Results

In the Example I was talking about earlier I made a simple cpu intensive Loop and benchmarked each of the three scenerio’s.

  NO Doevents – 0.011106160…. Seconds.

  Doevents WITH GetInputState – 0.397925155…. Seconds.

  Doevents ONLY – 8.273245901…. Seconds.

As you can see there are definitely performance/speed differences between each scenario. Of course No DoEvents() will be the highest performing scenerio but at the cost of freezing your application until the code has finished executing. But compare DoEvents() With GetInputState to DoEvents Only. Those are very noticeable differences in performance between the two methods. Simply checking the queue first by using GetInputState() increased performance MANY Times in that test. And as you already know by doing so you will Stop your application from freezing which will allow the user to interact with your application even when your running heavy cpu intensive code.

Anyways that’s all, I hope you got something of use from this tip. Take care… 🙂

 

Jason

How to Doevents for VB.NET, VB 2005 and higher

Click Star to Rate Post
1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5.00 out of 5)
 

The DoEvents() subroutine is still in VB.NET. It is located under the System.Windows.Forms.Application namespace.

            System.Windows.Forms.Application.DoEvents()

In Visual Basic 2005 and Newer you can access it quicker under the ‘MY’ namespace

            My.Application.DoEvents()

If you plan on using DoEvents() in a continuous loop, I would suggest using the GetInputState() api call.

The GetInputState() API will check whether there are any messages that needs to be processed and THEN it will call DoEvents() to process the messages. As a result, the code will be MANY times faster than if you used DoEvents() by itself.

Add this API call to the Declaration section of your application.

    Private Declare Function GetInputState Lib "user32" () As Integer

GetInputState can let you know if any messages are queued up for processing before you use DoEvents().
If there ARE messages that needs to be processed, THEN call DoEvents() and let the messages go ahead and process.

Basic example from my Snippets page:

Do
 '
 'Checks if any messages are queued up before DoEvents().
 'If there ARE messages that needs to be processed, THEN it will
 'call DoEvents() and let the messages go ahead and process.
 If GetInputState <> 0 Then Application.DoEvents()

Loop Until Me.Text = "Done"