Как использовать асинхронный TNetHTTPClient

#delphi #asynchronous

Вопрос:

Как использовать асинхронный 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;
 

Ошибка:

Ошибка при запросе заголовков: дескриптор находится в неправильном состоянии для запрошенной операции

Ответ №1:

В асинхронном режиме, как следует из названия, клиент выполняет запрос асинхронно в фоновом потоке.

При выполнении следующего кода происходит 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 или пользовательские потоки вместо анонимных потоков.

Комментарии:

1. Как, если хотите добавить цикл ? этот корект ? для i := от 0 до 50 начинайте //код asyn конец; конец;

2. Зависит от того, хотите ли вы делать параллельные запросы или один за другим?

3. Вы можете использовать TParallel.amp;For для такого цикла. TParallel.amp;Для(0, 50, процедура(I: Целое число) var httpclient… начало // ваш асинхронный код заканчивается);