Basically, what I need to do is this:
Show the user a "Please wait ..." form (lets call it waitForm
) on top of the main form, execute http methods (get and post), and close the waitForm
after I get the http response.
Since the http post method communicates with a physical device, it takes a while for the response to return (which is why I'm doing this in a worker thread, so the main thread doesn't appear to be "not responding").
I've set the http timeout to 1 minute. I've tried using an anonymous thread to execute the http methods so that the application doesn't go into "not responding", and so far its working as intended.
My problem here is that I need to use that response string further into the application after the thread is done. This is my code so far:
function TForm1.test: string;
var
ReqStream, ResStream: TStringStream;
http: TIdhttp;
command, commandName: string;
begin
TThread.CreateAnonymousThread(
procedure
begin
TThread.Synchronize(nil,
procedure
begin
waitForm.Label1.Caption := 'Please wait ...';
waitForm.BitBtn1.Enabled := False;
waitForm.FormStyle := fsStayOnTop;
waitForm.Show;
end);
try
http := TIdHTTP.Create(nil);
ReqStream := TStringStream.Create('', TEncoding.UTF8);
ResStream := TStringStream.Create('', TEncoding.UTF8);
try
command := '{"Amount":"69.00","TerminalName":"SIMULATE","omitSlipPrintingOnEFT":"1"}';
commandName := 'sale';
http.Request.ContentType := 'application/json';
http.Request.CharSet := 'utf-8';
http.Request.ContentEncoding := 'utf-8';
http.Request.Accept := 'application/json';
http.Request.Connection := 'keep-alive';
http.ConnectTimeout := 60000;
http.ReadTimeout := 60000;
ReqStream.WriteString(command);
ReqStream.Position := 0;
try
http.Post('http://localhost:5555/' + CommandName, ReqStream, ResStream);
http.Disconnect;
self.result := ResStream.DataString; // I know this can't be written like that
except
//
end;
finally
FreeAndNil(ReqStream);
FreeAndNil(http);
end;
finally
TThread.Synchronize(nil,
procedure
begin
waitForm.FormStyle := fsNormal;
waitForm.BitBtn1.Enabled := True;
waitForm.Close;
end);
end;
end).Start;
ShowMessage(result); // this is where I call next procedure to parse the response.
end;
After we get a result from the test()
function, I need to parse it and use it further in the application. fsStayOnTop
and disabling the buttons is the only solution that I have found to discourage the user from interacting with the main form since .ShowModal
is not an option because it blocks the function from continuing even with Synchronize()
(am I wrong here?).
I've also tried using ITask
and IFuture<string>
, but I can't seem to make it work as intended. Maybe I should be using anonymous functions.