- •Лабораторная работа № 3. Синхронизация потоков с использованием мfс
- •Задача синхронизации потоков
- •Создание и синхронизация потоков с использованием mfc
- •1. Синхронизация с использованием глобальной переменной
- •3. Взаимодействие с помощью объектов событий
- •1. Критические секции.
- •2. Мьютексы.
- •3. Семафор
- •Создание и выполнение потоков
- •Функция WaitForSingleObject
- •Cинхронизация в mfc
- •Cинхронизация в cMutex
- •Задания для самостоятельного выполнения.
Создание и синхронизация потоков с использованием mfc
Для работы с потоками в MFC предусмотрены следующие классы:
CWinThread
CSyncObject
CEvent
CCriticalSection
CMutex
CSemaphore
CSingleLock
CMultiLock
` Поток – отдельная ветвь выполнения программы. Он имеет свой стек и работает независимо от других потоков приложения.
Класс CWinThread представляет отдельный поток. Он присутствует во всех приложениях, потому что класс CWinApp (базовый для класса DirectDrawApp) является производным от CWinThread. Этот экземпляр класса CWinThread представляет основной поток приложения. Для того, чтобы добавить новые рабочие потоки, следует создать объекты CWinThread.
Класс CSyncObject является виртуальным. Непосредственное создание экземпляров этого класса не разрешается; он существует лишь для того, чтобы обеспечивать функциональные возможности производных классов. Класс CSyncObject является базовым для классов CEvent, CCriticalSection, CMutex и CSemaphore.
Классы CSingleLock и CMultiLock применяются для блокировки потоков по состоянию одного или нескольких событий. Класс CSingleLock блокирует поток до установки конкретного события, а CMultiLock — до установки одного или всех событий из заданного набора.
Cоздание простейшего потока:
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);
}
//Данный пример закрывает главное окно после выполнения потоковой функции
