SCARA, 6-Axis and Modules
Technical Support Notes

Article ID: T1090
Date: 10/31/02 (updated 4/10/03)
Products: VB Guide
Subject: MsgWait timer for VB and VC++ applications

Sometimes you may want to delay for a specified time in you VB (or VC++) application or cause your application to sleep momentarily while waiting for some event to occur.  The MsgWait sample code below is a subroutine that waits for a specified number of milliseconds.  The MsgWait routine is based on the WinAPI MsgWaitForMultipleObjects.  This allows your application to sleep until time has expired, and momentarily wake up to process events immediately.  

First, we will compare three different loop methods using VB.

The following Do..Loop causes your application to "hog" the CPU.  If you observe CPU Usage while this loop occurs, you will see 100%.  Events are processed immediately, but since the application is using the CPU more, the process that is sending events does not get as much CPU time, so event throughput is reduced.

Do
  DoEvents
Loop Until g_CycleComplete

This Do..Loop uses the WinAPI Sleep function.  This considerably reduces the CPU Usage, but events will not be processed as quickly.  In fact, no events will be processed during the Sleep time.  10 ms is the smallest interval that can be used.  

Do
  Sleep 10
  DoEvents
Loop Until g_CycleComplete

By using MsgWait, your application will not cause the CPU Usage to be 100%.  If an event occurs, it will be processed immediately.  This is more efficient for processing events, since your application will sleep until one or more events occur, process the events, then sleep again.

Do
  MsgWait 10
Loop Until g_CycleComplete

Also, VB does not have a delay timer, so MsgWait can be used for this purpose.
For example:

ExecuteMyFunc1
MsgWait 1000
ExecuteMyFunc2

The table below shows a comparison between the different loop methods.  The test was performed by running a SPEL+ task that executes SPELCom_Event in a loop with no delays.  As you can see, the MsgWait method allows the greatest event throughput with low CPU usage.

Loop method Approximate events per second CPU Usage
Do
  DoEvents
Loop Until g_CycleComplete
560 High
Do
  Sleep 10
  DoEvents
Loop Until g_CycleComplete
100 Low
Do
  MsgWait 10
Loop Until g_CycleComplete
640 Low

MsgWait for Visual Basic

Here is the MsgWait sample code for use with VB.  To use in your VB application, create a new code module and paste this sample code in the new module.

Option Explicit
Private Const QS_KEY = &H1
Private Const QS_MOUSEMOVE = &H2
Private Const QS_MOUSEBUTTON = &H4
Private Const QS_POSTMESSAGE = &H8
Private Const QS_TIMER = &H10
Private Const QS_PAINT = &H20
Private Const QS_SENDMESSAGE = &H40
Private Const QS_HOTKEY = &H80
Private Const QS_MOUSE = (QS_MOUSEMOVE Or QS_MOUSEBUTTON)
Private Const QS_INPUT = (QS_MOUSE Or QS_KEY)
Private Const QS_ALLEVENTS = (QS_INPUT Or QS_POSTMESSAGE Or QS_TIMER Or QS_PAINT Or QS_HOTKEY)
Private Const QS_ALLINPUT = (QS_SENDMESSAGE Or QS_PAINT Or QS_TIMER Or QS_POSTMESSAGE Or QS_MOUSEBUTTON Or QS_MOUSEMOVE Or QS_HOTKEY Or QS_KEY)

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Declare Function MsgWaitForMultipleObjects Lib "user32" (ByVal nCount As Long, pHandles As Long, ByVal fWaitAll As Long, ByVal dwMilliseconds As Long, ByVal dwWakeMask As Long) As Long

' *********************************************************
' * MsgWait
' *
' * Sleeps for a specified time but allows
' * events to process immediately
' *
' * Input: ms - milliseconds to wait
' * Output: none
' *
' * Notes: Resolution in NT 3.5 and above is 10 ms
' * Copyright (c) 2002, Epson America, Inc. FAR Division
' *********************************************************
Sub MsgWait(ByVal ms As Long)

  Dim start As Long, timeRemaining As Long, timeNow As Long

  start = GetTickCount()
  timeRemaining = ms
  Do
    ' Sleep until timeout or event occurs
    MsgWaitForMultipleObjects 0, 0, 0, timeRemaining, QS_ALLINPUT
    timeNow = GetTickCount()
    If timeNow - start >= timeRemaining Then
      Exit Sub
    ElseIf timeNow < start Then
      ' Handle GetTickCount 49.7 day wrap around
      start = timeNow
    End If
    timeRemaining = timeRemaining - (timeNow - start)
    start = timeNow
    DoEvents
  Loop
End Sub

MsgWait for Visual C++

Here is the MsgWait sample code for use with VC++.  A DoEvents function is also shown that processes Windows messages.  If messages are not processed, no events will be received. 

void DoEvents();
void MsgWait(long ms);

' *********************************************************
' * DoEvents
' *
' * Processes all Windows messages in the message queue
' * for the current thread
' * 
' * Input: none
' * Output: none
' *
' * Notes: Resolution in NT 3.5 and above is 10 ms
' * Copyright (c) 2003, Epson America, Inc. FAR Division
' *********************************************************
void DoEvents()
{
  MSG msg;
  long sts;

  do {
    if (sts = PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  } while (sts);
}

' *********************************************************
' * MsgWait
' *
' * Sleeps for a specified time but allows
' * events to process immediately
' *
' * Input: ms - milliseconds to wait
' * Output: none
' *
' * Notes: Resolution in NT 3.5 and above is 10 ms
' * Copyright (c) 2003, Epson America, Inc. FAR Division
' *********************************************************
void MsgWait(long ms)
{
  long start, timeRemaining, timeNow;

  start = GetTickCount();
  timeRemaining = ms;
  do {
    // Sleep until timeout or event occurs
    MsgWaitForMultipleObjects(0, 0, 0, timeRemaining, QS_ALLINPUT);
    timeNow = GetTickCount();
    if (timeNow - start >= timeRemaining)
      return;
    else if (timeNow < start)
      // Handle GetTickCount 49.7 day wrap around
      start = timeNow;
    timeRemaining = timeRemaining - (timeNow - start);
    start = timeNow;
    DoEvents();
  } while(1);
}

 


 

 

Click here to return to the EPSON Robots home page
The Power of Choice!