unit HandleForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  THandleFrm = class(TForm)
    CreateBtn: TButton;
    CloseOwnerBtn: TButton;
    CloseNonOwnerBtn: TButton;
    RelBtn: TButton;
    procedure CreateBtnClick(Sender: TObject);
    procedure CloseOwnerBtnClick(Sender: TObject);
    procedure CloseNonOwnerBtnClick(Sender: TObject);
    procedure RelBtnClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    Semaphore: THandle;
  end;

var
  HandleFrm: THandleFrm;

implementation

uses HandleThreads;

{$R *.DFM}

procedure THandleFrm.CreateBtnClick(Sender: TObject);

begin
  Semaphore := CreateSemaphore(nil, 1, 1, nil);
  WaitForSingleObject(Semaphore, INFINITE);
  THandleThread.Create(false);
  THandleThread.Create(false);
  ShowMessage('Threads Created.');
end;

procedure THandleFrm.CloseOwnerBtnClick(Sender: TObject);
begin
  CloseHandle(Semaphore);
end;

procedure THandleFrm.CloseNonOwnerBtnClick(Sender: TObject);
begin
  ReleaseSemaphore(Semaphore, 1, nil);
  CloseHandle(Semaphore);
end;

procedure THandleFrm.RelBtnClick(Sender: TObject);
begin
  ReleaseSemaphore(Semaphore, 1, nil);
end;

end.

unit HandleThreads;

interface

uses
  Classes, Windows, SysUtils, Dialogs;

type
  THandleThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

implementation

uses HandleForm;

procedure THandleThread.Execute;

var
  RetVal: integer;

begin
  RetVal := WaitForSingleObject(HandleFrm.Semaphore, 10000);
  case RetVal of
    WAIT_OBJECT_0: ShowMessage('Unblocked: WAIT_OBJECT_0');
    WAIT_ABANDONED: ShowMessage('Unblocked: WAIT_ABANDONED');
    WAIT_TIMEOUT: ShowMessage('Unblocked: WAIT_TIMEOUT');
  else
    ShowMessage('Unblocked. Unknown return code.');
  end;
end;

end.