Using Wait Functions

Windows CE supports two types of wait functions, single-object and multiple-objects. The single object function is WaitForSingleObject. The multiple object functions are WaitForMultipleObjects and MsgWaitForMultipleObjects.

The WaitForSingleObject function requires a handle of one synchronization object. This function returns when one of the following occurs:

The WaitForMultipleObjects and MsgWaitForMultipleObjects functions enable the calling thread to specify an array containing one or more synchronization object handles. These functions return when one of the following occurs:

The following code example shows how to use the CreateEvent function to create two event objects. It then uses the two created objects as parameters in the function call to WaitForMultipleObjects. The WaitForMultipleObjects function does not return until one of the objects is set to signaled.

HANDLE hEvents[2]; 
DWORD i, dwEvent; 

for (i = 0; i < 2; i++) 
{ 
   hEvents[i] = CreateEvent( 
      NULL,            // no security attributes
      FALSE,           // auto-reset event object
      FALSE,           // initial state is nonsignaled
      NULL);           // unnamed object
   if (hEvents[i] == NULL) 
   { 
      printf("CreateEvent error: %d\n", GetLastError() ); 
      ExitProcess(0); 
   } 
} 

dwEvent = WaitForMultipleObjects( 
   2,                  // number of objects in array
   hEvents,            // array of objects
   FALSE,              // wait for any
   INFINITE);          // indefinite wait

switch (dwEvent) 
{ 
   case WAIT_OBJECT_0 + 0: 
      break; 

   case WAIT_OBJECT_0 + 1: 
      break; 

   default: 
      printf("Wait error: %d\n", GetLastError()); 
      ExitProcess(0); 
}

The MsgWaitForMultipleObjects function is similar to WaitForMultipleObjects, except that it allows you to specify input event objects in the object handle array. You select the type of input event to wait for in the dwWakeMask parameter. MsgWaitForMultipleObjects does not return if there is unread input of the specified type in the queue. It returns only when new input arrives.

For example, a thread can use MsgWaitForMultipleObjects with its dwWakeMask parameter set to QS_KEY. This blocks its execution until the state of a specified object has been set to signaled and there is keyboard input available in the thread's input queue. The thread can use the GetMessage or PeekMessage function to retrieve the input.

When waiting for the states of all objects to be set to signaled, the multiple-object functions do not modify the states of the specified objects until the states of all objects have been set to signaled. For example, the state of a mutex object can be signaled, but the calling thread does not get ownership until the states of the other objects specified in the array have also been set to signaled. In the meantime, some other thread may get ownership of the mutex object, thereby setting its state to nonsignaled.

The following code example shows the use of the MsgWaitForMultipleObjects function in a message loop. The loop continues until a WM_QUIT message appears in the queue. The dwWakeMask parameter is set to QS_ALLINPUT so all messages are checked.

int MessageLoop
   ( 
      HANDLE* lphObjects,         // handles that need to be waited on 
      int     cObjects            // number of handles to wait on 
   )
{ 
      while (TRUE)
      {
         // block-local variable 
         DWORD result ; 
         MSG msg ; 

         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
         { 
            if (msg.message == WM_QUIT)  
               return 1; 
            DispatchMessage(&msg); 
         }

         result = MsgWaitForMultipleObjects(cObjects, lphObjects, 
                  FALSE, INFINITE, QS_ALLINPUT); 

         if (result == (WAIT_OBJECT_0 + cObjects))
         {
             continue;
         } 
         else 
         {
             Other Code (result - WAIT_OBJECT_0) ; 
         }
   }
}

Be careful when using the wait functions and code that directly or indirectly create windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. If you have a thread that uses a wait function with no time-out interval, the system will deadlock. Two examples of code that indirectly create windows are DDE and COM CoInitialize. If you have a thread that creates windows, use MsgWaitForMultipleObjects rather than the other wait functions.