Einzelnen Beitrag anzeigen

Benutzerbild von Christoph Schneider
Christoph Schneider

Registriert seit: 7. Okt 2008
Ort: CH-Baar
54 Beiträge
 
Delphi 11 Alexandria
 
#1

Long running Rest API Call mit THTTPClient

  Alt 27. Jun 2018, 10:20
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!
Christoph Schneider
  Mit Zitat antworten Zitat