При написании многопоточных приложений самое важное — контролировать синхронизированный доступ к ресурсам между потоками, чтобы обеспечить безопасную работу потоков. API Win 32 предоставляет набор объектов синхронизации, таких как семафор, мьютекс, критическая секция, событие и т. д., для решения этой проблемы.
Delphi инкапсулирует объекты событий и объекты критической секции в объекты Tevent и объекты TcriticalSection соответственно, что делает использование этих двух объектов простым и удобным. Однако если вы хотите использовать в программе Delphi такие объекты, как семафоры или мьютексы, вам придется прибегнуть к сложным функциям Win32 API, что очень неудобно для программистов, не знакомых с функциями Win32 API. Поэтому автор использовал Delphi для создания двух классов для инкапсуляции объектов семафора и мьютекса (TSemaphore и TMutex соответственно), надеясь быть полезными для большинства программистов Delphi.
1. Структура класса
Сначала мы абстрагируем объект-семафор и объект-мьютекс API Win32, создаем родительский класс THandleObjectEx, а затем получаем два подкласса Tsemphore и Tmutex от этого родительского класса.
Исходный код класса выглядит следующим образом:
модуль SyncobjsEx;
интерфейс
использует Windows, сообщения, SysUtils, классы, Syncobjs;
тип
THandleObjectEx = класс (THandleObject)
// THandleObjectEx — родительский класс класса взаимного исключения и класса семафора
Защищено
FHandle: THandle;
FLastError: Целое число;
общественный
деструктор Уничтожить;
процедура Освободить;переопределить;
функция WaitFor(Timeout: DWord): TWAitResult;
свойство LastError:Integer читает FLastError;
дескриптор свойства: THandle прочитано FHandle;
конец;
TMutex = class(THandleObjectEx)//Взаимоисключающий класс
общественный
конструктор Create(MutexAttributes: PSecurityAttributes; InitialOwner: Boolean; const Name:string);
отмена процедуры;
конец;
TSemaphore = класс (THandleObjectEx)
//Класс сигнального света
общественный
конструктор Create(SemaphoreAttributes: PSecurityAttributes;InitialCount:Integer;MaximumCount: целое число; const Name: string);
процедура Release (ReleaseCount: Integer = 1; PreviousCount: Pointer = nil перегрузка);