要监听来自 Rest 服务器的事件,我需要一个长时间运行的 HTTP 请求。
我们如何用 Delphi 做到这一点?
我当前的解决方案有效,但调用方的请求停止没有得到正确解决。我必须使用 Thread.Terminate 来停止线程。此线程终止会导致不必要的内存泄漏。这就是为什么我正在寻找另一种解决方案。
在没有从服务器接收到新数据的情况下,调用者也必须可以中断请求。我尝试使用 BeginExecute/BeginGet 进行异步调用,但我看到了同样的问题,即如果没有来自服务器的数据,请求就无法随时停止。
这是我的代码,它最终可以在不同的平台(Win/OSX/Android)上工作:
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;