• TIdAntiFreeze与TIdhttp配合使用注意事项


    在C++builder中使用idhttp抓取网页,造成窗口无反应的假死状态(所谓的假死就是由于在主线程中执行get或者post使用同步的方式,如果网页一直不返回,将会造成主界面不响应的现象)。通过搜索获得两种方法。

             1.写在线程中,但是调用比较麻烦

             2.使用C++builder 提供的idantifreeze(必须安装indy)。在indy misc中将idfreeantifreeze放入程序中,

    将OnlyWhenIdle状态修改为False即可。方便简单。

    为什么方法2是可以的:原因就是TIdAntiFreeze的Process方法中实际上是调用Application.Processmessage();

    所以可以实现界面不卡顿的功能,但是同时这也存在一定的注意事项,如果在TIdhttp的get或者post的过程中或者程序按照一步一步往下执行还没有执行到post函数的位置,主线程接收到了其他的响应,主线程将会在执行到post的时候保存现场移交所有权,跳转到其他响应中去执行,当执行结束后,主线程将会重新返回该现场继续往下执行,(比如说,2个表位检测,表位1在响应函数HandleResult()中将会执行TIdhttp控件问网页要数据,在还没有执行到post之前,表位2的串口接收到响应报文,要同步到主线程执行handlresult();这个时候,主线程执行到表位1的Handlresult()执行到TIdhttp的post的位置,由于TIdhttp与TIdAntiFreeze配合使用,而在Tidhttp在执行post的使用会先执行TIdAntiFreeze的process函数,因此主线程将会直接跳转表位2的handleresult()去执行,当表位2的handleresult()执行完成之后,主线程将会重新跳转回表位的post位置继续往下执行,因此,如果不想让主线程的执行顺序是这样的,就不要将TIdAntiFreeze与TIdhttp配合使用,只使用Tidhttp控件就行,但是解决不了界面卡死现象。)因此如果程序存在这种逻辑,就需要注意了,你希不希望你的程序可以这样执行,如果可以这样执行是可以配合使用的,但是如果你不希望主线程在执行post或者get的时候跳转走,那就不要使用TIdAntiFreeze控件,但是这样不能解决卡死现象,有利有弊吧,根据自己的业务场景自己定义使用。

    =====================================

    直接采用Delphi自带Control控件INDY组件为例.新建个工程,放上个TIdHTTPControl控件,一个TIdAntiFreezeControl控件,一个TProgressBar用于显示下载进度.最后放上一个TButton用于开始执行我们命令.

    procedure TForm1.Button1Click(Sender: TObject);//点击按钮时候开始下载我们文件
    var
    MyStream:TMemoryStream;
    begin
    IdAntiFreeze1.OnlyWhenIdle:=False;//设置使有反应.
    MyStream:=TMemoryStream.Create;
    try
    IdHTTP1.Get('http://www.138soft.com/download/Mp3ToExe.zip',MyStream);//下载我站点一个ZIP文件
    except//INDYControl控件一般要使用这种try..except结构.
    Showmessage('网络出错!');
    MyStream.Free;
    Exit;
    end;
    MyStream.SaveToFile('c:\Mp3ToExe.zip');
    MyStream.Free;
    Showmessage('OK');
    end;

    procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
    const AWorkCountMax: Integer);//开始下载前,将ProgressBar1最大值设置为需要接收数据大小.
    begin
    ProgressBar1.Max:=AWorkCountMax;
    ProgressBar1.Min:=0;
    ProgressBar1.Position:=0;
    end;

    procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
    const AWorkCount: Integer);//接收数据时候,进度将在ProgressBar1显示出来.
    begin
    ProgressBar1.Position:=ProgressBar1.Position+AWorkCount;
    end;

      IdHTTP1Get还有一种形式就是获取串:例如,上面可以改写成:

    procedure TForm1.Button1Click(Sender: TObject);
    var
    MyStr:String;
    begin
    IdAntiFreeze1.OnlyWhenIdle:=False;//设置使有反应.
    try
    MyStr:=IdHTTP1.Get('http://www.138soft.com/default.htm');
    except
    Showmessage('网络出错!');
    Exit;
    end;
    Showmessage(MyStr);
    end;

  • 相关阅读:
    LeetCode-636-函数的独占时间
    Java NIO 关键概念之 Buffer
    62. 不同路径-动态规划-双百代码
    docker 安装 redis
    旋转图像操作(90°、180°、270°)+ jpg 和png相互转换、resize尺寸大小 + padding 补黑边-长方形保持长宽比
    高学历毕业生,该学单片机还是plc?
    东北天坐标系与84坐标系的相互转换
    gcc和g++的爱恨纠葛
    线束测试仪怎么使用的,ATX-3000线束检测仪基本操作流程
    鸿蒙开发游戏(四)---大鱼吃小鱼(互吃升级)
  • 原文地址:https://blog.csdn.net/u013196348/article/details/126048430