delphi 如何使用异步TNetHTTPClient

mfuanj7w  于 2023-04-20  发布在  其他
关注(0)|答案(2)|浏览(339)

如何使用异步TNetHTTPClient?我尝试了以下代码,但它显示错误。

procedure TForm1.Button1Click(Sender: TObject);
var
  httpclient: TNetHTTPClient;
  output: string;
begin
  httpclient := TNetHTTPClient.Create(nil);
  try
      httpclient.Asynchronous := True;
      output := httpclient.Get('https://google.com').ContentAsString;
  finally
    httpclient.Free;
  end;
end;

错误:
查询标题时出错:对于请求的操作,句柄处于错误的状态

2admgd59

2admgd591#

在异步模式下,顾名思义,客户端在后台线程中异步运行请求。
当执行以下代码时,ContentAsString失败,因为此时请求未完成。

output := httpclient.Get('https://google.com').ContentAsString

如果您想在异步模式下使用HTTP客户端,则必须使用完成处理程序在请求完成后运行相应的代码。

procedure TForm1.Button1Click(Sender: TObject);
var
  httpclient: TNetHTTPClient;
begin
  httpclient := TNetHTTPClient.Create(nil);
  httpclient.Asynchronous := True;
  httpclient.OnRequestCompleted := HTTPRequestCompleted;
  httpclient.Get('https://google.com');
end;

procedure TForm1.HTTPRequestCompleted(const Sender: TObject; const AResponse: IHTTPResponse);
var
  output: string;
begin
  output := AResponse.ContentAsString;
  Sender.Free;
end;

在异步模式下使用HTTP客户端通常比在后台线程的同步模式下使用它更复杂(特别是从内存管理方面)。
下面是使用匿名后台线程的等效示例:

procedure TForm1.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    var
      httpclient: TNetHTTPClient;
      output: string;
    begin
      httpclient := TNetHTTPClient.Create(nil);
      try
        httpclient.Asynchronous := False;
        output := httpclient.Get('https://google.com').ContentAsString;
      finally
        httpclient.Free;
      end;
    end).Start;
end;

当然,您也可以使用TTask或自定义线程来代替匿名线程。

tuwxkamq

tuwxkamq2#

这里你有两个版本-一个用于GET,一个用于POST(带响应)。小心你想使用它的服务器上的Modsecurity问题和其他服务器设置,这可能会导致代码无法按预期工作(就像我在服务器上处理POST时发生的那样)。
对于POST,我使用Params.Add('input =' + TNetEncoding.URL.Encode(AText));你也可以使用text=代替input=,我将响应存储在URLMemo中,你可以根据需要更改它。

procedure TUExtractForm.LoadURLAsync(const AURL: string);
const
  CONST_TIMEOUT = 30000;
begin
  TTask.Run(
    procedure
    var
      HttpClient: TNetHTTPClient;
      HTTPRequest: TNetHTTPRequest;
    begin
      try
        HttpClient := TNetHTTPClient.Create(nil);
        try
          HttpClient.ConnectionTimeout := CONST_TIMEOUT; // Timeout
          HttpClient.ResponseTimeout := CONST_TIMEOUT;   // Timeout
          HTTPRequest := TNetHTTPRequest.Create(HttpClient);
          HTTPRequest.Client := HttpClient;
          HTTPRequest.OnRequestCompleted := HTTPRequestCompleted;
          HTTPRequest.OnRequestError := HTTPRequestError;

          HTTPRequest.Get(AURL);
        finally
          HttpClient.Free;
        end;
      except
        on E: Exception do
          begin
            TThread.Queue(nil,
              procedure
              begin
                ShowMessageFmt('Error: %s', [E.Message]);
              end);
          end;
      end;
    end);
end;

procedure TUExtractForm.LoadURLAsyncPOST(const AURL, AText: string);
const
  CONST_TIMEOUT = 30000;
begin
  TTask.Run(
    procedure
    var
      HttpClient: TNetHTTPClient;
      HTTPRequest: TNetHTTPRequest;
      ParamsStream: TBytesStream;
    begin
      ParamsStream := nil;
      try
        HttpClient := TNetHTTPClient.Create(nil);
        try
          HttpClient.ConnectionTimeout := CONST_TIMEOUT; // Timeout
          HttpClient.ResponseTimeout := CONST_TIMEOUT;   // Timeout
          HTTPRequest := TNetHTTPRequest.Create(HttpClient);
          HTTPRequest.Client := HttpClient;
          HTTPRequest.OnRequestCompleted := HTTPRequestCompleted;
          HTTPRequest.OnRequestError := HTTPRequestError;
          HTTPRequest.CustomHeaders['Content-Type'] := 'application/x-www-form-urlencoded';

          ParamsStream := TBytesStream.Create(TEncoding.UTF8.GetBytes('input=' + TNetEncoding.URL.Encode(AText)));
          HTTPRequest.Post(AURL, ParamsStream);
        finally
          HttpClient.Free;
          ParamsStream.Free;
        end;
      except
        on E: Exception do
          begin
            TThread.Queue(nil,
              procedure
              begin
                ShowMessageFmt('Error: %s', [E.Message]);
              end);
          end;
      end;
    end);
end;

procedure TUExtractForm.HTTPRequestCompleted(const Sender: TObject; const AResponse: IHTTPResponse);
var
  Content: string;
begin
  if AResponse.StatusCode = 200 then
    begin
      Content := AResponse.ContentAsString;
      // replace #$A with new line
      Content := StringReplace(Content, #$A, sLineBreak, [rfReplaceAll]);
      URLMemo.Text := Content;
    end;
end;

procedure TUExtractForm.HTTPRequestError(const Sender: TObject; const AError: string);
begin
  ShowMessageFmt('Error: %s', [AError]);
end;

相关问题