Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 712|回复: 0

Delphi 10.3.1 TNetHttpClient在多线程中存在的问题及解决方法。

[复制链接]
  • TA的每日心情
    奋斗
    2024-9-22 15:19
  • 签到天数: 795 天

    [LV.10]以坛为家III

    2050

    主题

    2108

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    724084
    发表于 2021-4-28 10:12:01 | 显示全部楼层 |阅读模式

    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中。

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-10-1 02:35 , Processed in 0.065467 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表