Multithreading – Delphi threading using trestrequest
I am new to restrequest tool I hope someone has solved the problem of waiting for asynchronous calls to complete
I have a program that generates hundreds of different API calls, then calls the result of the processing, passes the result back to the API execution process, and continues.
Only when such a call is made without a thread, the problem is still that the software hangs until the call is completed... In order to try to solve this problem, I changed restrequest Execute; To restrequest ExecuteAsync();, But now my problem is that my code continues without waiting for a response from restrequest
Trying to bypass this problem again, I tried several solutions, even API RESTRequest. ExecuteAsync(). WaitFor; (throw error thread error: invalid handler (6))
Is there any way I can change the following function to run as a separate thread (only the execution part runs in the thread is very important)... Basically, I just want to display an animation loading icon every time I call the function, and for the rest of my code, until this function is completed
I want a simpler solution instead of starting using multithreading completely
code
function run_api_command():boolean; begin result := false; RESTResponse.Content.Empty; RESTAdapter.Dataset:= ds_action; RESTAdapter.RootElement:= ''; try RESTRequest.ExecuteAsync; if(ds_action.Active = false) then ds_action.Active:=true; if(ds_action.FieldByName('result').AsString<>'Success') then begin showmessage(ds_action.FieldByName('result').AsString); end else begin RESTAdapter.RootElement:= 'data'; result := true; end; except on E: Exception do begin if(e.Message = 'REST request Failed: Error sending data: (12007) The server name or address Could not be resolved') then begin if(messagedlg('Could not connect to server. Would you like to retry?',mterror,[mbYes,mbNo],0)=mrYes) then begin result := run_api_command(); end; end else begin showmessage(RESTResponse.Content); end; end; end; end;
Solution
Executeasync () runs in the worker thread (the trestexecutionthread object it returns) However, executeasync() has an afreethread parameter that defaults to true As the documentation clearly states:
Therefore, by default, calling waitfor () on the returned object pointer will crash
Even if the returned object pointer is valid when afreethread = true, calling waitfor() will still crash When the freeonterminate property of the TThread object is set to true, the object releases its underlying API handle when the thread terminates, which will cause waitfor() to fail with an "invalid handle" error TThread. Waitfor() has a logic error 1 when TThread When freeonterminate = true, it does not handle this situation
(1 this bug has been introduced in Delphi 6. At that time, TThread was rewritten as Kylix support, and it has never been corrected in later versions.)
If you want the caller to wait for a response from the rest server, do one of the following:
>Use execute() instead of executeasync(), or at least set afreethread = false, so that you can call waitfor() (or equivalent, such as msgwaitformultipleobjects()) on the thread object, and then deal with the consequences of execution waiting. Main UI thread: > use execute() but move the whole logic to your own worker thread and synchronize it with the main UI thread as needed
A better solution is not to wait at all, which means redesigning the code flow Continue to use executeasync(), but pass a completion callback that will be called when the request completes and let the callback drive the next step in the code Don't actively wait for executeasync to complete, let it notify you
procedure run_api_command(); begin ... RESTRequest.ExecuteAsync( procedure begin if not RESTResponse.Status.Success then begin // do something ... end else begin // do something else ... end; end,True ); end;