Ao escrever aplicativos multithread, o mais importante é controlar o acesso sincronizado a recursos entre threads para garantir a operação segura dos threads. A API Win 32 fornece um conjunto de objetos de sincronização, como Semaphore, Mutex, Critical Section e Event, para resolver este problema.
O Delphi encapsula objetos de evento e objetos de seção crítica em objetos Tevent e objetos TcriticalSection respectivamente, tornando o uso desses dois objetos simples e conveniente. Porém, se você quiser usar objetos como semáforos ou mutexes em um programa Delphi, deverá recorrer a funções complexas da API Win32, o que é muito inconveniente para programadores que não estão familiarizados com as funções da API Win32. Portanto, o autor usou Delphi para construir duas classes para encapsular os objetos semáforo e mutex (TSemaphore e TMutex respectivamente), esperando ser útil para a maioria dos programadores Delphi.
1. Estrutura de classes
Primeiro abstraímos o objeto semáforo e o objeto mutex da API Win32, construímos uma classe pai THandleObjectEx e, em seguida, derivamos duas subclasses Tsemphore e Tmutex dessa classe pai.
O código fonte da classe é o seguinte:
unidade SyncobjsEx;
interface
usa Windows, Mensagens, SysUtils, Classes, Syncobjs;
tipo
THandleObjectEx = classe(THandleObject)
// THandleObjectEx é a classe pai da classe de exclusão mútua e da classe de semáforo
Protegido
FHandle: THandle;
FLastError: Inteiro;
público
substituição do destruidor;
Liberação de procedimento; substituir;
função WaitFor (Tempo limite: DWord): TWaitResult;
propriedade LastError:Número inteiro lido FLastError;
identificador de propriedade: THandle lê FHandle;
fim;
TMutex = class(THandleObjectEx)//Classe mutuamente exclusiva
público
construtor Create (MutexAttributes: PSecurityAttributes; InitialOwner: Boolean; const Name:string);
liberação de procedimento;
fim;
TSemaphore = classe(THandleObjectEx)
//Classe de luz de sinalização
público
construtor Create(SemaphoreAttributes: PSecurityAttributes;InitialCount:Integer;MaximumCount: inteiro; const Nome: string);
procedimento Release(ReleaseCount: Integer=1;PreviousCount:Pointer=nil sobrecarga);