
- •Лабораторна робота №1 Загальні теоретичні відомості:
- •Питання для самоконтролю:
- •Лабораторна робота №2 Системний реєстр Windows
- •Огляд системного реєстру
- •Скарбниця імен
- •Призначений для користувача модуль
- •Системний блок
- •Загальний модуль
- •Ключі конфігурації
- •Конфігураційні файли win.Ini і system.Ini
- •Питання для самоконтролю:
- •Лабораторная работа №3
- •Основы программирования в операционной системе Windows
- •Вызов функций api
- •Структура окна
- •Принципы построения оконных приложений
- •Структура окна
- •Параметры dwExStyle:
- •Параметры dwStyle :
- •12. Функция ExitProcess :
- •17. Функция BeginPaint:
- •Сообщения, посылаемые списку
- •Вопросы для подготовки к сдаче лабораторной работы.
- •Лабораторная работа №4
- •Язык описания ресурсов
- •Пиктограммы
- •Курсоры
- •Акселераторы
- •Api – функции
- •Вопросы для подготовки к сдаче лабораторной работы.
- •Лабораторная работа №5
- •Типы многозадачности
- •Использование многопоточности в приложениях Delphi
- •Синхронизации потоков
- •Критические секции
- •Пример создания многопоточного приложения в Delphi:
- •Лабораторная работа №6 «Специальные объекты синхронизации»
- •Событие (event)
- •Мьютекс (mutex )
- •Семафор (semaphore)
- •Crytical Sections
Лабораторная работа №6 «Специальные объекты синхронизации»
Краткие теоретические сведенья:
Иногда при работе с несколькими потоками или процессами появляется необходимость синхронизировать выполнениедвух или более из них. Причина этого чаще всего заключается в том, что два или более потоков могут требовать доступ к разделяемому ресурсу, который реально не может быть предоставлен сразу нескольким потокам.
Разделяемымназывается ресурс, доступ к которому могут одновременно получать несколько выполняющихся задач.
Потоки находятся в состоянии ожидания, пока ожидаемые ими объекты заняты. Как только объект освобождается, ОС будит поток и позволяет продолжить выполнение. Для приостановки потока и перевода его в состояние ожидания освобождения объекта используется функция
DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);
где hObject - описатель ожидаемого объекта ядра, а второй параметр - максимальное время ожидания объекта.
Поток создает объект ядра при помощи семейства функций Create (CreateSemaphore, CreateThread и т.д.), после чего объект посредством описателя становится доступным всем потокам данного процесса. Копия описателя может быть получена при помощи функции DuplicateHandle и передана другому процессу, после чего потоки смогут воспользоваться этим объектом для синхронизации.
Перейдем к рассмотрению объектов ядра, которые предназначены специально для синхронизации. Это события, семафоры и мьютексы.
Кратко рассмотрим каждый из них:
Событие (event)
Пожалуй, самый простой и фундаментальный синхронизирующий объект. Это всего лишь флаг, которому функциями SetEvent/ResetEventможно задать состояние: сигнализирующее или нейтральное.Событие– это самый удобный способ передать сигнал ожидающему потоку, что некое событие свершилось (потому оно так и называется), и можно продолжать работу. С помощью события легко решить проблему синхронизации при инициализации рабочего потока:
// для простоты описатель события будет храниться в глобальной переменной:
HANDLE g_hEventInitComplete = NULL; // никогда не оставляем переменную неинициализированной!
{ // код в главном потоке
// создание события
g_hEventInitComplete = ::CreateEvent( NULL,
FALSE,
FALSE, // начальное состояние - нейтральное
NULL );
if( !g_hEventInitComplete ) { /* обработка ошибок */ }
// создание рабочего потока
DWORD idWorkerThread = 0;
HANDLE hWorkerThread = ::CreateThread( NULL, 0, &WorkerThreadProc, NULL, 0, &idWorkerThread );
if( !hWorkerThread ) { /* обработка ошибки */ }
// ожидание сигнала от рабочего потока
DWORD dwWaitResult = ::WaitForSingleObject( g_hEventInitComplete, INFINITE );
if( dwWaitResult != WAIT_OBJECT_0 ) { /* ошибка */ }
// рабочий поток завершил инициализацию.
VERIFY( ::CloseHandle( g_hEventInitComplete ) ); // закрытие ненужных объектов
g_hEventInitComplete = NULL;
}
// функция рабочего потока
DWORD WINAPI WorkerThreadProc( LPVOID _parameter )
{
InitializeWorker(); // инициализация
// сигнализация, что инициализация завершена
BOOL isOk = ::SetEvent( g_hEventInitComplete );
if( !isOk ) { /* ошибка */ }
}
Надо заметить, что существуют две заметно отличающиеся разновидности событий. Мы можем выбрать одну из них с помощью второго параметра функции CreateEvent. Если он TRUE, создается событие, состояние которого управляется только вручную, то есть функциямиSetEvent/ResetEvent. Если же он FALSE, будет создано событие с автосбросом. Это означает, что как только некий поток, ожидающий данного события, будет освобожден сигналом от этого события, оно автоматически будет сброшено обратно в нейтральное состояние. Наиболее ярко их отличие проявляется в ситуации, когда одного события ожидают сразу несколько потоков. Событие с ручным управлением подобно стартовому пистолету. Как только оно будет установлено в сигнализирующее состояние, будут освобождены сразу все потоки. Событие же с автосбросом похоже на турникет в метро: оно отпустит лишь один поток и вернется в нейтральное состояние.