Информация об изменениях

Сообщение Re[4]: Как правильно приостановить поток? от 31.01.2017 7:03

Изменено 31.01.2017 7:04 RussianFellow

Re[4]: Как правильно приостановить поток?
Ясно, спасибо!

Но это был пример использования событий при помощи MFC. А как без MFC?

На www.firststeps.ru я нашёл пример:

HANDLE CreateEvent
(
    LPSECURITY_ATTRIBUTES lpEventAttributes,    // атрибут защиты
    BOOL bManualReset,                // тип сброса TRUE - ручной
    BOOL bInitialState,            // начальное состояние TRUE - сигнальное
    LPCTSTR lpName                // имя обьекта
);

Если функция успешна, то вернется дескриптор события. В том случае, если с таким именем событие уже создано, то вернется дескриптор уже созданного события, а GetLastError() вернет код ERROR_ALREADY_EXISTS. Но функция может вернуть и NULL, если объект события создать не удалось совсем. Функция SetEvent() меняет состояние на сигнальное (есть событие).


BOOL SetEvent
(
    HANDLE hEvent        // дескриптор события
);

В случае успеха вернет ненулевое значение. А функция ResetEvent() меняет состояние на невыделенное (нет события):


BOOL ResetEvent
(
    HANDLE hEvent        // дескриптор события
);

Пример смотрим.


// TestEvent.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "process.h" 

HANDLE event;

void Test1(void *);
void Test2(void *);
void Test3(void *);

void main()
{
    event=CreateEvent(NULL,TRUE,FALSE,"FirstStep");
    if (_beginthread(Test1,1024,NULL)==-1)
        cout << "Error begin thread " << endl;
    if (_beginthread(Test2,1024,NULL)==-1)
        cout << "Error begin thread " << endl;
    if (_beginthread(Test3,1024,NULL)==-1)
        cout << "Error begin thread " << endl;
    if (event!=NULL){
        Sleep(1000);
        SetEvent(event);
        Sleep(1000);
        ResetEvent(event);
        CloseHandle(event);
    } else {
        cout << "error create event" << endl;
    }

}

void Test1(void *)
{
    DWORD dwWaitResult;
    while(dwWaitResult!=WAIT_OBJECT_0) {
        dwWaitResult = WaitForSingleObject(event,1);
        cout << "Test 1 TIMEOUT" << endl;
    }
    cout << "Event Test 1 " << endl;
    _endthread();
}

void Test2(void *)
{
    DWORD dwWaitResult;
    while(dwWaitResult!=WAIT_OBJECT_0){
        dwWaitResult = WaitForSingleObject(event,1);
        cout << "Test 2 TIMEOUT" << endl;
    }
    cout << "Event Test 2 " << endl;
    _endthread();
}

void Test3(void *)
{
    DWORD dwWaitResult;
    while(dwWaitResult!=WAIT_OBJECT_0){
        dwWaitResult = WaitForSingleObject(event,1);
        cout << "Test 3 TIMEOUT" << endl;
    }
    cout << "Event Test 3 " << endl;
    _endthread();
}

Создает объект Event, запускает три потока. Каждый поток ждет когда объект синхронизации перейдет в сигнальное состояние. После некоторой задержки устанавливаем его в сигнальное состояние SetEvent(), выжидаем некоторое время, чтобы потоки среагировали и сбрасываем ResetEvent(). Обратите внимание, что в данном случае в отличии от всех других объектов синхронизации потоков может быть любое количество.


То есть я задал flag = 2 для приостановки работы потока, а в потоковой функции я написал

if (*threadflag==2)
// если поток был приостановлен
{
DWORD dwWairResult;
while (dwWaitResult!=WAIT_OBJECT_0)
// ждём, пока не появится событие (по которому надо или продолжить работу потока, или выйти из него)
{
dwWaitResult = WaitForSIngleObject(event,1);
}
if (*threadflag==0)
{
FreeMemory(); // освобождение ресурсов
return; // выход из функции потока
}
// если *threadflag==1 , то продолжаем работу потока
}

то правильно ли я сделал?
Re[4]: Как правильно приостановить поток?
Ясно, спасибо!

Но это был пример использования событий при помощи MFC. А как без MFC?

На www.firststeps.ru я нашёл пример:

HANDLE CreateEvent
(
    LPSECURITY_ATTRIBUTES lpEventAttributes,    // атрибут защиты
    BOOL bManualReset,                // тип сброса TRUE - ручной
    BOOL bInitialState,            // начальное состояние TRUE - сигнальное
    LPCTSTR lpName                // имя обьекта
);

Если функция успешна, то вернется дескриптор события. В том случае, если с таким именем событие уже создано, то вернется дескриптор уже созданного события, а GetLastError() вернет код ERROR_ALREADY_EXISTS. Но функция может вернуть и NULL, если объект события создать не удалось совсем. Функция SetEvent() меняет состояние на сигнальное (есть событие).


BOOL SetEvent
(
    HANDLE hEvent        // дескриптор события
);

В случае успеха вернет ненулевое значение. А функция ResetEvent() меняет состояние на невыделенное (нет события):


BOOL ResetEvent
(
    HANDLE hEvent        // дескриптор события
);

Пример смотрим.


// TestEvent.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "process.h" 

HANDLE event;

void Test1(void *);
void Test2(void *);
void Test3(void *);

void main()
{
    event=CreateEvent(NULL,TRUE,FALSE,"FirstStep");
    if (_beginthread(Test1,1024,NULL)==-1)
        cout << "Error begin thread " << endl;
    if (_beginthread(Test2,1024,NULL)==-1)
        cout << "Error begin thread " << endl;
    if (_beginthread(Test3,1024,NULL)==-1)
        cout << "Error begin thread " << endl;
    if (event!=NULL){
        Sleep(1000);
        SetEvent(event);
        Sleep(1000);
        ResetEvent(event);
        CloseHandle(event);
    } else {
        cout << "error create event" << endl;
    }

}

void Test1(void *)
{
    DWORD dwWaitResult;
    while(dwWaitResult!=WAIT_OBJECT_0) {
        dwWaitResult = WaitForSingleObject(event,1);
        cout << "Test 1 TIMEOUT" << endl;
    }
    cout << "Event Test 1 " << endl;
    _endthread();
}

void Test2(void *)
{
    DWORD dwWaitResult;
    while(dwWaitResult!=WAIT_OBJECT_0){
        dwWaitResult = WaitForSingleObject(event,1);
        cout << "Test 2 TIMEOUT" << endl;
    }
    cout << "Event Test 2 " << endl;
    _endthread();
}

void Test3(void *)
{
    DWORD dwWaitResult;
    while(dwWaitResult!=WAIT_OBJECT_0){
        dwWaitResult = WaitForSingleObject(event,1);
        cout << "Test 3 TIMEOUT" << endl;
    }
    cout << "Event Test 3 " << endl;
    _endthread();
}

Создает объект Event, запускает три потока. Каждый поток ждет когда объект синхронизации перейдет в сигнальное состояние. После некоторой задержки устанавливаем его в сигнальное состояние SetEvent(), выжидаем некоторое время, чтобы потоки среагировали и сбрасываем ResetEvent(). Обратите внимание, что в данном случае в отличии от всех других объектов синхронизации потоков может быть любое количество.


То есть я задал flag = 2 для приостановки работы потока, а в потоковой функции я написал

if (*threadflag==2)
// если поток был приостановлен
{
    DWORD  dwWairResult;
    while (dwWaitResult!=WAIT_OBJECT_0)
    // ждём, пока не появится событие (по которому надо или продолжить работу потока, или выйти из него)
    {
        dwWaitResult = WaitForSIngleObject(event,1);
    }
    if (*threadflag==0)
    {
        FreeMemory(); // освобождение ресурсов
        return; // выход из функции потока
    }
    // если *threadflag==1 , то продолжаем работу потока
}


то правильно ли я сделал?