unit HttpRequestThread;
interface
uses
System.Generics.Collections,
System.SyncObjs,
System.Classes;
type
TResponseNotify =
procedure(
const Request, Response :
string )
of object;
THttpRequestThread =
class( TThread )
private
FCS : TCriticalSection;
FEvent : TEvent;
FQueue : TQueue<
string>;
FOnResponse : TResponseNotify;
procedure SetOnResponse(
const Value : TResponseNotify );
function GetOnResponse : TResponseNotify;
function GetQueueItem :
string;
procedure ProcessQueueItem;
procedure DoResponseNotify(
const ARequest, AResponse :
string );
protected
procedure Execute;
override;
procedure TerminatedSet;
override;
public
constructor Create;
destructor Destroy;
override;
procedure Add(
const ARequest :
string );
property OnResponse : TResponseNotify
read GetOnResponse
write SetOnResponse;
end;
implementation
uses
System.SysUtils,
IdException,
IdHTTP;
{ THttpRequestThread }
procedure THttpRequestThread.Add(
const ARequest :
string );
begin
FCS.Enter;
try
FQueue.Enqueue( ARequest );
FEvent.SetEvent;
finally
FCS.Leave;
end;
end;
constructor THttpRequestThread.Create;
begin
FCS := TCriticalSection.Create;
FEvent := TEvent.Create(
nil, False, False, '
' );
FQueue := TQueue<
string>.Create;
inherited Create( False );
end;
destructor THttpRequestThread.Destroy;
begin
inherited;
FreeAndNil( FQueue );
FreeAndNil( FEvent );
FreeAndNil( FCS );
end;
procedure THttpRequestThread.DoResponseNotify(
const ARequest, AResponse :
string );
begin
if MainThreadID = CurrentThread.ThreadID
then
begin
if Assigned( OnResponse )
then
OnResponse( ARequest, AResponse );
end
else
Queue(
procedure
begin
DoResponseNotify( ARequest, AResponse );
end );
end;
procedure THttpRequestThread.Execute;
begin
inherited;
while not Terminated
do
begin
FEvent.WaitFor;
if not Terminated
then
ProcessQueueItem;
end;
end;
function THttpRequestThread.GetOnResponse : TResponseNotify;
begin
FCS.Enter;
try
Result := FOnResponse;
finally
FCS.Leave;
end;
end;
function THttpRequestThread.GetQueueItem :
string;
begin
FCS.Enter;
try
Result := FQueue.Dequeue;
if FQueue.Count > 0
then
FEvent.SetEvent;
finally
FCS.Leave;
end;
end;
procedure THttpRequestThread.ProcessQueueItem;
var
LRequest :
string;
LResponse :
string;
LHttp : TIdHTTP;
begin
LHttp := TIdHTTP.Create(
nil );
LHttp.HandleRedirects := True;
try
LRequest := GetQueueItem;
try
LResponse := LHttp.Get( LRequest );
except
on E : EIdException
do
begin
LResponse := E.ClassName + '
: ' + E.
Message;
end;
end;
DoResponseNotify( LRequest, LResponse );
finally
LHttp.Free;
end;
end;
procedure THttpRequestThread.SetOnResponse(
const Value : TResponseNotify );
begin
FCS.Enter;
try
FOnResponse := Value;
finally
FCS.Leave;
end;
end;
procedure THttpRequestThread.TerminatedSet;
begin
inherited;
FEvent.SetEvent;
end;
end.