我有一个程序,它生成数百个不同的api调用,然后调用处理结果,并将结果传递回调用api执行的过程,然后继续…
只有在没有线程的情况下进行此类调用时,问题仍然是软件挂起,直到调用完成…为了尝试解决这个问题,我更改了RESTRequest.Execute;到RESTRequest.ExecuteAsync();,但现在我的问题是我的代码继续而不等待restrequest的响应.
再次尝试绕过这个问题我尝试了几个解决方案,甚至是api.RESTRequest.ExecuteAsync().WaitFor; (抛出错误线程错误:处理程序无效(6))
有没有什么方法我可以改变下面的函数作为一个单独的线程运行(只有执行部分在线程中运行很重要)…基本上我只想在每次调用函数时显示一个动画加载图标,并且对于我的其余代码来说,直到此功能完成…
我希望有一个更简单的解决方案,而不是开始使用多线程完全..
码
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;
解决方法
When the
AFreeThread
parameter is set to False,this method returns a 07001 to this execution thread.Note: If the
AFreeThread
parameter is set to True,the method returns an invalid reference.
因此,默认情况下,对返回的对象指针调用WaitFor()将会崩溃.
即使返回的对象指针在AFreeThread = True时有效,调用WaitFor()仍然会崩溃.当TThread对象的FreeOnTerminate属性设置为True时,该对象在线程终止时释放其底层API句柄,这会导致WaitFor()失败并出现“句柄无效”错误. TThread.WaitFor()有一个逻辑错误1,当TThread.FreeOnTerminate = True时,它不处理这种情况.
(1这个bug一直在Delphi 6中引入,当时TThread被重写为Kylix支持,并且在以后的版本中从未纠正过.)
如果您希望调用者等待来自REST服务器的响应,请执行以下操作之一:
>使用Execute()而不是ExecuteAsync(),或者至少设置AFreeThread = False,这样你就可以在线程对象上调用WaitFor()(或等效的,如MsgWaitForMultipleObjects()),然后处理执行等待的后果主UI线程:
>使用Execute(),但将整个逻辑移动到您自己的工作线程,并根据需要使其与主UI线程同步.
更好的解决方案是根本不等待,这意味着重新设计代码流.继续使用ExecuteAsync(),但传递一个完成回调,该回调将在请求完成时调用,并让该回调驱动代码中的下一步.不要主动等待ExecuteAsync完成,让它通知你.
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;