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

我对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;

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...