Контрольная работа: Особливості багатозадачності в середовищі Windows
CloseHandle(hDayTimer);
CloseHandle(hAlarmTimer);
_endthreadex(0);
return 0;
};
int main(int argc, char* argv[])
{
// this event shows the thread when to finish working
hTerminateEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
unsigned uThreadID;
HANDLE hThread;
// creating thread
hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc, 0, 0,&uThreadID);
puts("Press any key to exit.");
getch();
// setting the event
SetEvent(hTerminateEvent);
//waiting for closing of the thread
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;}
Багатопотоковість і графіка
Є ще одна особливість при роботі з об'єктами синхронізації. Справа в тім, що Windows 95 досить "важко" взаємодіє зі своєю графічною системою в багатозадачному режимі. Це пояснюється тим, що в Windows 95 графічна підсистема частково залишилася 16-розрядної і звертання до такого коду приводить до захоплення системного семафора, що виключає, Win16Mutex, що запобігає одночасний доступ декількох процесів (потоків) до такого коду. Твердження авторів деяких книг по Windows 95 про те, що це не є перешкодою, якщо ви працюєте в цілком 32-розрядному додатку, на практиці виявляється неспроможним.
Отже, основною проблемою стала неможливість коректного зняття з виконання графічного потоку. Зняття вироблялося по наступному алгоритму. Кожен потік у нескінченному циклі перевіряв прапор-сигнал про завершення. Якщо прапор був виставлений, то потік виходив з нескінченного циклу і завершувався штатним шляхом. У спрощеному виді процедура зняття описана в ліс тингу 3.
Такий код ідеально працював, якщо вироблялося зняття потоку, що не звертається до графічної системи Windows (або рідко звертається - раз у кілька секунд). Якщо ж потік увесь час що-небудь малював, то спроба зняття закінчувалася виходом з функції WaitForSingleObject через перевищення часу чекання (значення, щоповертається, WAIT_TIMEOUT), тобто підпрограма, що знімається, не одержувала керування, поки ми "сиділи" у функції WaitForSingleObject. Збільшення періоду чекання (наприклад, до 10 с) ні до чого не приводило - потік усі десять секунд уперто чекав звільнення об'єкта і зрештою виходив зі значенням WAIT_TIMEOUT.
Причина, по якій потік не знімався, узагалі ж зрозуміла - йому не передавалося керування. Можна спробувати примусово зробити це, збільшивши пріоритет потоку, що знімається:
void breakTask(GF_Task* tsk)
{
DWORD result;