Wait Functions (Windows Embedded CE 6.0)

1/6/2010

Windows Embedded CE supports single-object and multiple-object wait functions that block or unblock a thread, based on the state of the object.

The single-object function is WaitForSingleObject.

The multiple-object functions are WaitForMultipleObjects and MsgWaitForMultipleObjects.

The WaitForSingleObject function sets a thread to wait for a single object. The object can be a synchronization object, such as an event or mutex, or the object can be a handle to a process and thread.

Handles are signaled when their processes or threads terminate. Thus, a process can monitor another process or thread and perform some action based on the status of the process or thread.

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 events occurs:

  • The state of a specified object is set to signaled.
  • The timeout interval elapses.
    You can set the timeout interval to INFINITE to specify that the timeout does not time out.

Windows Embedded CE does not support waiting for all objects to be signaled.

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

int EventsExample (void)
{
   HANDLE hEvents[2];
   DWORD dwEvent;
   int i;
   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)
      {
         // Your error handling code goes here.
         MessageBox (NULL, TEXT("CreateEvent error!"), TEXT("Error"), MB_OK);
         // You can use GetLastError to obtain more information.
         return 0;
      }
   }
   // Put code that uses the events here; that is, startup of threads, which will set the events when completed.
   dwEvent = WaitForMultipleObjects
   (
      2, // Number of objects in an array
      hEvents, // Array of objects
      FALSE, // Wait for any (required under Windows Embedded CE)
      INFINITE); // Indefinite wait
   switch (dwEvent)
   {
      case WAIT_OBJECT_0 + 0: // First event was signaled
      case WAIT_OBJECT_0 + 1: // Second event was signaled
      break;
      default:
      // Your error handling code goes here.
      MessageBox (NULL, TEXT("Wait error!"), TEXT("Error"), MB_OK);
      // You can use GetLastError to obtain more information.
      return 0;
   }
   return 1;
} // End of EventsExample code

MsgWaitForMultipleObjects is similar to WaitForMultipleObjects, except that it enables you to specify input event objects in the object handle array. 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 it until the state of a specified object is signaled or until keyboard input is available in the thread's input queue. The thread can use the GetMessage or PeekMessage function to obtain the input.

The following code example shows how to use MsgWaitForMultipleObjects 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 that all messages are checked.

int MessageLoop
   (
      HANDLE* lphObjects, // Handles that need to be waited on
      int     iObjCount ) // Number of handles to wait on
      {
         while (TRUE)
         {
            // Block-local variables
            DWORD dwResult;
            MSG msgCurrent;
            while (PeekMessage (&msgCurrent, NULL, 0, 0, PM_REMOVE))
            {
               if (WM_QUIT == msgCurrent.message)
               return 1;
               DispatchMessage (&msgCurrent);
            }
         dwResult = MsgWaitForMultipleObjects (iObjCount, lphObjects, FALSE, INFINITE, QS_ALLINPUT);
         if (dwResult == DWORD(WAIT_OBJECT_0 + iObjCount))
         {
            // Some input was received - go around loop again
            continue;
         }
      else 
      {
         // Check for errors and handle them here. If not an error,
         // write code which processes the result here.  Be sure to
         // create code that provides some way to get out of the loop!
         // The index for the signaled is 
         // (dwResult - WAIT_OBJECT_0).
      }
   }
}

Note

Be careful when using wait functions and code that directly or indirectly creates windows. If a thread creates windows, it must process messages. Message broadcasts are sent to all windows in the system. If a thread uses a wait function with no timeout interval, the system deadlocks. One example of code that indirectly creates a window is the Component Object Model (COM) CoInitialize function. If you have a thread that creates windows, use MsgWaitForMultipleObjects, rather than the other wait functions.

See Also

Concepts

Synchronization