在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;