gpt4 book ai didi

multithreading - Delphi 线程与 TRestRequest

转载 作者:行者123 更新时间:2023-12-03 14:57:02 37 4
gpt4 key购买 nike

我对 RestRequest 工具还比较陌生。我希望有人已经解决了等待异步调用完成的问题......

我有一个程序,它进行数百个不同的 api 调用,然后调用处理结果,并将结果传递回调用 api 执行的过程,然后该过程可以继续...

与往常一样,在没有线程的情况下进行此类调用的唯一问题是软件会挂起,直到调用完成...为了尝试解决此问题,我将 RESTRequest.Execute; 更改为 RESTRequest .ExecuteAsync();,但现在我的问题是我的代码继续运行而不等待重新请求的响应。

再次尝试绕过这个问题,我尝试了几种解决方案,甚至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;

最佳答案

ExecuteAsync() 在工作线程(它返回的 TRESTExecutionThread 对象)中运行。但是,ExecuteAsync() 有一个 AFreeThread 参数,默认为 True。作为documentation明确指出:

When the AFreeThread parameter is set to False, this method returns a reference 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 这个错误早在 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;

关于multithreading - Delphi 线程与 TRestRequest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46063689/

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com