unit uLater;
interface
uses
System.Generics.Collections,
System.SysUtils,
System.SyncObjs,
System.Classes;
type
Later =
class
private type
TProcItem =
record
Proc : TProc;
constructor Create( AProc : TProc );
end;
TLaterThread =
class( TThread )
private
FCS : TCriticalSection;
FEvent : TEvent;
FQueue : TQueue<TProcItem>;
private
function GetProc : TProcItem;
protected
procedure Execute;
override;
procedure TerminatedSet;
override;
public
constructor Create;
destructor Destroy;
override;
procedure AddProc( AProc : TProc );
end;
private
class var FThread : TLaterThread;
protected
class constructor Create;
class destructor Destroy;
public
class procedure Execute( AProc : TProc );
end;
implementation
{ Later }
class constructor Later.Create;
begin
FThread := TLaterThread.Create;
end;
class destructor Later.Destroy;
begin
FThread.Free;
end;
class procedure Later.Execute( AProc : TProc );
begin
FThread.AddProc( AProc );
end;
{ Later.TLaterThread }
procedure Later.TLaterThread.AddProc( AProc : TProc );
begin
FCS.Enter;
try
FQueue.Enqueue( TProcItem.Create( AProc ) );
FEvent.SetEvent;
finally
FCS.Leave;
end;
end;
constructor Later.TLaterThread.Create;
begin
inherited Create( False );
FCS := TCriticalSection.Create;
FEvent := TEvent.Create(
nil, True, False, '
' );
FQueue := TQueue<TProcItem>.Create;
end;
destructor Later.TLaterThread.Destroy;
begin
FCS.Enter;
try
FQueue.Free;
inherited;
FEvent.Free;
finally
FCS.Leave;
FreeAndNil( FCS );
end;
end;
procedure Later.TLaterThread.Execute;
var
LProc : TProcItem;
begin
inherited;
while not Terminated
do
begin
if ( FEvent.WaitFor( INFINITE ) = TWaitResult.wrSignaled )
and not Terminated
then
begin
LProc := GetProc;
Queue(
procedure
begin
LProc.Proc( );
end );
end;
end;
end;
function Later.TLaterThread.GetProc : TProcItem;
begin
FCS.Enter;
try
Result := FQueue.Dequeue;
if FQueue.Count = 0
then
FEvent.ResetEvent;
finally
FCS.Leave;
end;
end;
procedure Later.TLaterThread.TerminatedSet;
begin
inherited;
FEvent.SetEvent;
end;
{ Later.TProcItem }
constructor Later.TProcItem.Create( AProc : TProc );
begin
Proc := AProc;
end;
end.