Windows CE supports single-object and multiple-object wait functions that block or unblock a thread based on the signaled or nonsignaled state of the object. The single object function is WaitForSingleObject. The multiple object functions are WaitForMultipleObjects and MsgWaitForMultipleObjects.
The WaitForSingleObject function enables a thread wait on 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:
Windows 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 function call to WaitForMultipleObjects. WaitForMultipleObjects does not return until one of the objects is set to 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 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. 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.
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).
}
}
} // End of MessageLoop example code
Note Be careful when using the wait functions and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all the windows in the system. If you have a thread that uses a wait function with no time-out interval, the system will deadlock. 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.