Поток не останавливается при использовании WaitForSingleObject()

Следующий код принимает кнопки от 0 до 9 и в зависимости от нажатой кнопки добавляет к глобальной переменной от 1 до 9 (при нажатии соответствующей кнопки) или вычитает 5 при нажатии на 0. Прибавление реализовано в функции ThreadProc1, вычитание в ThreadProc2. При каждом нажатии на кнопку создаётся поток, производит вычисления и записывает результаты в журнал. Последние два значения в журнале - результат работы в "дочернем" потоке и результат работы в основном потоке. Я хотел синхронизировать выполнение потоков с использованием "ручного" события, но WaitForSingleObject почему то не задерживает поток.

#include <windows.h>
#include <conio.h>
#include <iostream>
#include <time.h>

using namespace std;

HANDLE hThread;  // дескриптор создаваемого потока
HANDLE hEvent;
DWORD IDThread;  // идентификатор потока

LPTHREAD_START_ROUTINE ThreadProc1(struct log1* p);
LPTHREAD_START_ROUTINE ThreadProc2(struct log1* p);

int F = 0;             // разделяемая глобальная переменная
clock_t wtime = 200;   // время задержки (мс)
void waiting(clock_t dt); // функция задержки
// Журнал 
struct log1 {
    int nom;        // порядковый номер операции
    int key;        // код нажатой клавиши
    DWORD ID;       // идентификатор созданного потока
    clock_t t1; // время начала операции
    clock_t t2; // время завершения операции
    clock_t t3; // время входа в критический участок
    int F;      // результат операции в дочернем потоке
    int Fc;     // результат операции главном потоке  
} mylog[1000];
//=================================================
int main()  // главный поток
{
    int i = 0;      // счетчик операций
    int j = 1;      // счетчик вывода строк журнала 
    int key = 1;        // код нажатой клавиши
    int flag = 1;   // признак завершения программы 
    int Fcontr; // переменная-дублер
    mylog[1].t2 = 0; // признак того, что поток не завершен
    mylog[1].t3 = 0;
    Fcontr = F;


    hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);  //создание события с ручным режим переключения состояния
    if (hEvent == NULL)                            //если событие не создано вывести ошибку
    {
        cout << "Ошибка создания события.\n";
        return 0;
    }
    // повторять пока flag !=0 или i<1000
    while (flag || i >= 1000)
    {
        //Прием кода нажатой клавиши
        if (_kbhit() != 0)
        {
            key = _getch();
            // формирование переменной-дублера
            if (key < 58 || key > 48) Fcontr = Fcontr + key - 48;
            if (key == 48) Fcontr = Fcontr - 5;
            //Проверка кода нажатой клавиши
            switch (key)
            {
            case 27: {flag = 0; break; } // признак выхода из 
                                      // программы (Esc)
            case 48:        // нажата клавиша "0"
            {
                i = ++i; //следующая операция       
                 // формируем строку журнала          
                mylog[i].nom = i;
                mylog[i].key = key;
                mylog[i].t2 = 0;
                mylog[i].t3 = 0;
                mylog[i].F = 0;
                mylog[i].Fc = Fcontr;
                mylog[i].t1 = clock();
                // создание потока без немедленного запуска
                hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, &mylog[i], CREATE_SUSPENDED, &IDThread);
                if (hThread == NULL)
                {
                    cout << "Thread error" << key << endl;
                    _getch();
                    return 0;
                }
                else
                {
                    // запуск потока       
                    mylog[i].ID = IDThread;
                    ResumeThread(hThread);
                }
                break;
            }
            case 50:        // нажата клавиша "2"
            case 51:        // нажата клавиша "3"
            case 52:        // нажата клавиша "4"
            case 53:        // нажата клавиша "5"
            case 54:        // нажата клавиша "6"
            case 55:        // нажата клавиша "7"
            case 56:        // нажата клавиша "8"
            case 57:        // нажата клавиша "9"
            case 49:        // нажата клавиша "1"
            {
                i = ++i; //следующая операция       
              // формируем строку журнала          
                mylog[i].nom = i;
                mylog[i].key = key;
                mylog[i].t2 = 0;
                mylog[i].t3 = 0;
                mylog[i].F = 0;
                mylog[i].Fc = Fcontr;
                mylog[i].t1 = clock();
                // создание потока без немедленного запуска
                hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, &mylog[i], CREATE_SUSPENDED, &IDThread);
                if (hThread == NULL)
                {
                    cout << "Thread error" << key << endl;
                    _getch();
                    return 0;
                }
                else
                {
                    // запуск потока       
                    mylog[i].ID = IDThread;
                    ResumeThread(hThread);  //ожидание завершения события
                }
            }
            }
        }
        // завершение работы потока проверяется по 
        // сформированному в функции 
        // потока значению времени t2
        if (mylog[j].t2 && mylog[j].t3 != 0)
        {
            // вывод j-й строки журнала
            cout << j << "  " << mylog[j].key << "  " << mylog[j].ID << "  " << mylog[j].t1 << "  " << mylog[i].t3 << "  " << mylog[j].t2 << "  " << mylog[j].F << "  " << mylog[j].Fc << endl;
            j = ++j;   // следующая строка журнала
        }
    } // повторять пока flag !=0 или i<1000
    _getch();
    return 0;
}

// функция потока: имитация "чтения", корректировки 
// и "записи" разделяемой переменной F
// параметр - указатель на текущую строку журнала 
LPTHREAD_START_ROUTINE ThreadProc1(struct log1* p)
{
    int Fbuf;
    // чтение разделяемой переменной в буферную переменную
    (*p).t3 = clock();
    WaitForSingleObject(hEvent, INFINITE);
    ResetEvent(hEvent);
    Fbuf = F;
    waiting(wtime);  // задержка
    // корректировка буферной переменной
    if ((*p).key < 58 || (*p).key > 48) Fbuf = Fbuf + (*p).key - 48;
    waiting(wtime);  // задержка
    // запись из буферной переменной в разделяемую переменную
    F = Fbuf;
    SetEvent(hEvent);  //конец критического учатка, сброс состояния события
    // запись результата в текущую строку журнала
    (*p).F = F;
    (*p).t2 = clock(); // время окончания работы потока
    return 0;
}

LPTHREAD_START_ROUTINE ThreadProc2(struct log1* p)
{
    int Fbuf;
    (*p).t3 = clock();
    WaitForSingleObject(hEvent, INFINITE);
    ResetEvent(hEvent);  //вход в критический участок, событие отмечается
    Fbuf = F;
    waiting(wtime);
    if ((*p).key == 48) Fbuf = Fbuf - 5;
    waiting(wtime);
    F = Fbuf; 
    SetEvent(hEvent);  //конец критического участка, сброс состояния события
    (*p).F = F;
    (*p).t2 = clock();
    return 0;
}

// функция задержки
// параметр - время задержки в мс
void waiting(clock_t dt) {
    clock_t tn;
    tn = clock();
    while (clock() - tn < dt);
    return;
}

Ответы (0 шт):