加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

多线程 – 使用TRestRequest进行Delphi线程处理

发布时间:2020-12-14 16:46:54 所属栏目:Java 来源:网络整理
导读:我对RestRequest工具比较陌生.我希望有人解决了等待异步调用完成的问题…… 我有一个程序,它生成数百个不同的api调用,然后调用处理结果,并将结果传递回调用api执行的过程,然后继续… 只有在没有线程的情况下进行此类调用时,问题仍然是软件挂起,直到调用完成
我对RestRequest工具比较陌生.我希望有人解决了等待异步调用完成的问题……

我有一个程序,它生成数百个不同的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;

解决方法

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

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;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读