Ich benötige für einen Event von einem Rest-Server einen long running HTTP-Request.
Wie macht man das sauber mit Delphi Board mitteln?
Meine aktuelle Lösung läuft zwar nach einigem Probieren. Der Stop des Request geht leider nur auf die harte Tour mit einem Thread.Terminate und hinterlässt dann als Folge unschöne Memory Leaks.
Delphi-Quellcode:
type
TMyRestAPI =
class
private
fClient: THTTPClient;
fStream: TMemoryStream;
fReadPos: Int64;
fOnReceiveData:
procedure(
const data:
string)
of object;
procedure OnRecData(
const Sender: TObject; AContentLength: Int64;
AReadCount: Int64;
var Abort: Boolean);
public
procedure StartRequest(
const URL:
string);
procedure StopRequest;
end;
procedure TMyRestAPI.StartRequest(
const URL:
string);
begin
fClient := THTTPClient.Create;
fClient.HandleRedirects := true;
fClient.Accept := '
text/event-stream';
fClient.OnReceiveData := OnRecData;
fStream := TMemoryStream.Create;
fReadPos := 0;
fThread := TThread.CreateAnonymousThread(
procedure
begin
fClient.Get(
URL, fStream);
end);
fThread.Start;
end;
procedure TMyRestAPI.OnRecData(
const Sender: TObject; AContentLength: Int64;
AReadCount: Int64;
var Abort: Boolean);
var
ss: TStringStream;
resp:
string;
begin
ss := TStringStream.Create;
try
fStream.Position := readPos;
ss.CopyFrom(fStream, AReadCount - fReadPos);
fOnReceiveData(ss.DataString);
fReadPos := AReadCount;
finally
ss.Free;
end;
end;
procedure TMyRestAPI.StopRequest;
begin
fThread.Terminate;
fClient.Free;
fStream.Free;
end;
Da ich den Request alle paar Stunden repetitiv abbrechen muss um anschliessend mit einem neuen Token zu restarten, suche ich eine bessere Lösung.
Bei Verwendung der Asynchronen Calls mit BeginExecute/BeginGet lässt sich der laufende Request leider auch nur stoppen, wenn Daten vom Server empfangen werden.
Gerade dies ist aber bei einem long running rest
API Call über längere Zeit hinweg nicht der Fall und ich fand kein Weg, den asynchrone Request zu einem beliebigen Zeitpunkt zu stoppen.
Async := fClient.BeginGet(URL);
Meine Lösung sollte unter Firemonkey auf allen Plattformen laufen, dass wäre mindestens dass Ziel!