Создание потоков (MFC)


Поток – отдельная ветвь выполнения программы. Имеет свой стек и работает независимо от других потоков приложения.

Создание простейшего потока
AfxBeginThread(ProcName,param,priority)
ProcName – имя функции, которая будет выполнятся в новом потоке
param – указатель типа LPVOID или void* на аргумент ProcName
priority – константа, определяющая приоритет нового потока по отношению к основному

Может принимать одно из следующих значений:
THREAD_PRIORITY_ABOVE_NORMAL  // на один пункт ниже нормального
THREAD_PRIORITY_BELOW_NORMAL  //на один пункт выше нормального
THREAD_PRIORITY_HIGHEST  //на два пункта выше нормального
THREAD_PRIORITY_IDLE  //базовый приоритет равный 1
THREAD_PRIORITY_LOWEST  //на два пункта ниже нормального
THREAD_PRIORITY_NORMAL  //нормальный приоритет
THREAD_PRIORITY_TIME_CRITICAL  //приоритет равный 15
Приоритет потока определяет, как часто по отношению к другим выполняющимся потокам система будет передавать управление данному потоку
UINT ThreadProc(LPVOID param)  //Создание потоковой функции
{
   ::
MessageBox((HWND)param, ”Thread activated”,”Message from Thread” ,MB_OK);
   
return 0;
}

SomeFunc()
{
   
AfxBeginThread(ThreadProc,GetSafeHwnd()); //Запуск потока
}
Синхронизация работы потоков.

1. Глобальная переменная
bool bThreadstop;  //контрольная переменная

UINT ThreadProc(LPVOID param)  //Создание потоковой функции
{
   ::
MessageBox((HWND)param, ”Thread activated”,”Message from thread”,MB_OK);
   
while(!bThreadstop)
   {
        
//Выполнение опреаций
   
}

   ::
MessageBox((HWND)param, ”Thread ended”,”Message from thread”,MB_OK);
   
return 0;
}

SomeFunc()
{
   
bThreadstop=false;
   
AfxBeginThread(ThreadProc,GetSafeHwnd());  //Запуск потока
}

StopThread()
{
    
bThreadstop=true;  //остановка потока
}
2. Взаимодействие с помощью сообщений
const WM_THREADENDED = WM_USER+1;  //Это надо добавить в катры сообщений

afx_msg LONG OnThreadEnded(WPARAM wParam,LPARAM lParam);

ON_MESSAGE(WM_THREADENDDED,OnThreadEnded)

bool bThreadstop;  //контрольная переменная

UINT ThreadProc(LPVOID param)  //Создание потоковой функции
{
   ::
MessageBox((HWND)param, ”Thread activated”,”Message from thread”,MB_OK);
   
while(!bThreadstop)
   {
        
//Выполнение опреаций
   
}

   ::
PostMessage((HWND)param,WM_THREADENDED,(WPARAM)param,0); //Сообщение
   
return 0;
}

SomeFunc()
{
   
bThreadstop=false;
   
AfxBeginThread(ThreadProc,GetSafeHwnd()); //Запуск потока
}

StopThread()
{
   
bThreadstop=true;  //остановка потока
}

LONG OnThreadEnded(WPARAM wParam, LPARAM lParam)
{
   ::
MessageBox((HWND)wParam,”Thread Ended”,”Message from thread”, MB_OK);
}

//Данный пример закрывает главное окно после выполнения потоковой функции
3. Взаимодействие с помощью объектов событий

Объект событий CEvent может находится в одном из двух состояний – сигнализирует или молчит. Потоки отслеживают момент, когда объект события начинает сигнализировать, и начинаю выполнение операций.
CEvent ThreadStart;  //объект автоматически устанавливается в состояние молчания

ThreadStart.SetEvent();  //установка состояния сигнализации
Отслеживание состояния объекта осуществляется с помощью функции WinAPI WaitForSingleObject();
:: WaitForSingleObject(ThreadStart.m_hObject,INFINITE);
- первый параметр – дескриптор отслеживаемого события.
- второй параметр – время отслеживания. INFINITE – бесконечно.

В момент установки события WaitForSingleObject() вернет управление потоку.
В момент сброса события поток должен прекратить свою работу.
Для этого надо организовать постоянный опрос состояния события.

Это можно сделать следующим способом:
::WaitForSingleObject(ThreadStart.m_hObject,0);
Время 0 говорит о том, что надо опросить событие.
Если результат вызова этой функции равен WAIT_OBJECT_0, то объект в остоянии сигнализации. В других случаях – молчит.
CEvent ThreadStart;  //Объект начала работы потока
CEvent ThreadEnd;  //Объект окончания работы потока

UINT ThreadProc(LPVOID param)  //Создание потоковой функции
{
   ::
WaitForSingleObject(ThreadStart.m_hObject,INFINITE);  //ожидание запуска потока
   
::MessageBox((HWND)param, ”Thread activated”,”Message from thread”,MB_OK);
   
bool Running=true;
   
int result;
   
while(Running)
   {
        
//Выполнение опреаций

       
result=:: WaitForSingleObject(ThreadEnd.m_hObject,0);  //проверка завершения
       
if(result==WAIT_OBJECT_0)
           
Running=false;
   }

   ::
PostMessage((HWND)param,WM_CLOSE,0,0); //Сообщение

   
return 0;
}

Start()  //запуск потока
{
   
ThreadStart.SetEvent();
}

End()  //завершение потока
{
   
ThreadEnd.SetEvent();
}
Поток нужно создавать независимо от состояния событий.
 
« Предыдущая статья   Следующая статья »