Delphi 10.3.1 TNetHttpClient在多線程中存在的問題及解決方法。


Delphi 10.3.1發布了,對10.3.0存在的各種問題,做了大量的修正。但聽高勇說TNetHttpClient在多線程中存在問題,今天做了一下測試,確實如此,看來,還需要官方進一步修正!

具體測試方法,直接上代碼:

procedure TForm1.Button3Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 1 to 3 do // 大於2,無法測試通過.
  begin
    TThread.CreateAnonymousThread(
      procedure()
      var
        aHttpClient: TNethttpClient;
        AResponseContent: Tstream;
        cnt: Integer;
        ContentLength: Integer;
        tid:Cardinal;
      begin
        cnt := 0;
        tid:=TThread.Current.ThreadID;
        aHttpClient := TNethttpClient.Create(Self);//建立NetHttpClient實例,並用他不斷的訪問同一網址。
        try
          while true do
          begin
            Inc(cnt);
            // aHttpClient := TNethttpClient.Create(Self);
            AResponseContent := TMemoryStream.Create;
            try
              aHttpClient.Accept := 'text/javascript, text/html, application/xml, text/xml, /';
              aHttpClient.AcceptLanguage := 'en-US,en;q=0.8,fr;q=0.6';
              aHttpClient.UserAgent := 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36';
              try
                aHttpClient.Get('https://www.cnblogs.com/kinglandsoft/p/10383103.html',AResponseContent);//開始訪問並返回結果到AResponseContent流中.
              except
                On E: Exception do
                begin
                  TThread.Synchronize(nil,
                    procedure()
                    begin
                      if Memo1.Lines.Count > 500 then
                        Memo1.Lines.Clear;
                      Memo1.Lines.Add(E.Message);
                    end);
                end;
              end;
              ContentLength := AResponseContent.Size;//取得返回內容的長度,用來顯示

              TThread.Synchronize(nil,
                procedure()
                var
                  s: string;
                begin
                  s := Format('cnt=%d,ContentLength:%d in thread id:%s',
                    [cnt, ContentLength, tid.ToString]);
                  Label1.Text := s;
                  Memo1.Lines.Add(s);
                  if Memo1.Lines.Count > 500 then
                    Memo1.Lines.Clear;
                end);
            finally
              // aHttpClient.Free;
              AResponseContent.Free;
            end;
          end; // while true.
        finally
          aHttpClient.Free;
        end;
      end).Start;
  end;
end;

 實現思路,在線程中,建立一個NetHttpClient實例,用來訪問一個網址,同時建立幾個線程來運行NetHttpClient來訪問。結果,如果實例數=2,可以通過,大於2,則無法通過。另外換成HttpClient也是同樣的情況。此外,只是在android平台存在問題,win32平台正常。

向官方提交了這個問題,地址在https://quality.embarcadero.com/browse/RSP-23742,如果你也遇到,別忘記投一票,督促官方確認並修正。

跳過該問題的辦法,在官方沒有修正前,可以使用idHTTP來替代。

有解決方案了:

復制System.Net.HttpClient.pas單元到你的項目文件夾,修改THTTPClientExt的記錄結構為如下代碼:

  THTTPClientExt = record
    case Integer of
    0: (
      FPreemptiveAuthentication: Boolean;
      FSecureFailureReasons: THTTPSecureFailureReasons;
      FAutomaticDecompression: THTTPCompressionMethods
    );
    1: ( _pad: array[0 .. 7] of Byte ); end;

測試通過。

另外,如果不復制System.Net.HttpClient.pas到你的項目目錄,則需要把System.Net.HttpClient.pas所在目錄加入項目的Search Path中。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM