A general solution would be to spawn another thread:
type
PAsyncData = ^TAsyncData;
TAsyncData = record
Request, Response: String;
Ready: Cardinal;
end;
function GetHTTP_ThreadFunc(AsyncData: Pointer): PtrInt;
var
Data: PAsyncData absolute AsyncData;
Client: THTTPSend = Nil;
Buffer: TStringList;
begin
Data^.Response := 'Error';
Buffer := TStringList.Create();
try
Client := THTTPSend.Create();
if Client.HTTPMethod('GET', Data^.Request) then begin
Buffer.LoadFromStream(Client.Document);
Data^.Response := Buffer.Text.Trim();
end;
finally
Client.Free();
end;
InterlockedExchange(Data^.Ready, 1);
Buffer.Free();
Result := 0;
end;
function GetHTTP(const Request: String): String;
var
Data: TAsyncData;
begin
Data := Default(TAsyncData);
Data.Request := Request;
BeginThread(@GetHTTP_ThreadFunc, @Data);
while InterlockedCompareExchange(Data.Ready, 0, 0) <> 1 do begin
Application.ProcessMessages();
Sleep(16);
end;
Result := Data.Response;
end;
You'd then use it like this:
function GetResponse(request: WideString): String;
begin
GifView.PathToGIF:= ExePath+'pics\ConnToServer.gif';
GifView.Show;
Result := GetHTTP(request);
GifView.Close;
end;
The function is split in two: a frontend (
GetHTTP) and a backend (
GetHTTP_ThreadFunc) because spawning a thread requires a
TThreadFunc, which isn't ergonomic to use on its own. The
TAsyncData record is needed for passing data between and synchronizing the threads, using atomic operations for the latter (not really necessary here, but good practice anyway).
While waiting for the request in the newly spawned thread to complete,
GetHTTP repeatedly calls
Application.ProcessMessages so that the UI remains responsive, but I capped it at around 60 times per second (using
Sleep(16)), because doing it too often only drives up CPU usage with diminishing returns.
If you're doing lots of requests, you might want to use a thread pool to avoid the overhead of creating a thread every time.