Тем не менее, если событие находится в свободном состоянии и для него не установлен флаг bManualReset(передаётся в функцию создания события), то оно переводится в занятое состояние и возвращается значение WAIT_OBJECT_0. Поэтому после выполнения вызова WaitForSingleObject(hEvent, 0) событие с bManualReset = FALSE всегда окажется в несвободном состоянии. Аналогичная ситуация и с Mutex'ами - поток захватывает Mutex.
Поэтому, банальное добавление таких "проверок" может разладить всю работу программы. Чтобы избаыиться от этого, нужно делать проверки так:
if ((WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
{
SetEvent(hEvent);
...
}
if (WaitForSingleObject(hMutex, 0) == WAIT_OBJECT_0)
{
ReleaseMutex(hMutex);
...
}
Т.е. если мы обнаруживаем, что мы поменяли состояние объекта - то нужно вернуть его в прежнее состояние. Что касается планирования, то действительно, при вызове любой(!) функции, ожидающей объекта(естественно, в том числе и WaitForSingleObject()), поток теряет остаток кванта процессорного времени и вызывается планировщик для выбора нового потока. Однако, если других готовых потоков нет - то, естественно, продолжится выполнение потока, вызвавшего функцию ожидания.
P.S. Ну и на последок - маленькая программка-пример и её вывод:
#include <stdio.h>
#include <windows.h>
int main(void)
{
HANDLE hEvent;
hEvent = CreateEvent(NULL, 0, 1, NULL);
printf("%d\n", WaitForSingleObject(hEvent, 0)==WAIT_OBJECT_0);
printf("%d\n", WaitForSingleObject(hEvent, 0)==WAIT_OBJECT_0);
return 0;
}
Вывод: