Delphi:使用 Indy (TidHttp) 下载更新文件时出现问题
Delphi: Issues during download of update file, with Indy (TidHttp)
- Q1:为什么下载过程中模态窗体无法关闭
- Q2:为什么下载完成后进度条不是100%丰富(重绘的一种方式?)
- 问题 3:为什么我在运行期间停止并重新启动与 Web 服务器的连接?
下载传输正在停止而不显示任何错误并且
永不继续?我该怎么做才能得到并捕获错误然后去
回到初始状态(下载安装进度条在
位置 0)
备注:IdAntiFreeze 已激活
procedure Tform_update.button_downloadClick(Sender: TObject);
var
FS: TFileStream;
url, file_name: String;
begin
//execute download
if button_download.Tag = 0 then
begin
Fdone:= False;
Fcancel:= False;
url:= APP_DOMAIN + '/downloads/Setup.exe';
file_name:= 'C:\Temp\Setup.exe';
if FileExists(file_name) then DeleteFile(file_name);
try
FS:= TFileStream.Create(file_name, fmCreate);
Http:= TIdHTTP.Create(nil);
Http.OnWorkBegin:= HttpWorkBegin;
Http.OnWork:= HttpWork;
Http.Get(url, FS);
finally
FS.Free;
Http.Free;
if Fdone then ModalResult:= mrOk;
end;
end
else
//cancel download
begin
Fcancel:= True;
end;
end;
procedure Tform_update.HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
ContentLength: Int64;
Percent: Integer;
begin
ContentLength:= Http.Response.ContentLength;
if AWorkCount = ContentLength then Fdone:= True; //
if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and (ContentLength > 0) then
begin
sleep(15);
Percent := 100 * AWorkCount div ContentLength;
progress_bar.Position:= Percent;
end;
//stop download
if Fcancel and Http.Connected then
begin
Http.IOHandler.InputBuffer.Clear;
Http.Disconnect;
Fcancel:= False;
button_download.Caption:= _('Download and Install');
button_download.Tag:= 0;
progress_bar.Position:= 0;
end;
end;
procedure Tform_update.HttpWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
if AWorkMode <> wmRead then Exit;
button_download.Tag:= 1;
button_download.Caption:= _('Cancel');
end;
procedure Tform_update.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Fcancel:= True;
end;
另一种方法是使用TThread 来控制执行。像这样:
ThreadUpdate = class(TThread)
protected
procedure Execute; override;
public
procedure ThreadUpdate.Execute;
begin
inherited;
while (not terminated) do
begin
//YOUR CODE HERE - maybe your button_download Click
Terminate;
end;
end;
您也可以尝试让 Windows 为您的应用程序处理消息。
if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and (ContentLength > 0) then
begin
sleep(15);
Percent := 100 * AWorkCount div ContentLength;
progress_bar.Position:= Percent;
**Application.ProcessMessages;**
end;
Q1。 Indy 正在阻止。 All Antifreeze 会定期调用 windows 消息处理。它不会阻止 Indy 的阻塞性质,因此除非您明确地有一种方法来处理错误,否则它不会按照您想要的方式运行。您需要在不同的线程中进行下载并使用您的表单来监视该线程的状态,而不是尝试依赖防冻剂。不要在该线程中放置任何 UI 操作,将它们留在主线程中,因此不要尝试从线程内更新进度条。例如,将同步变量设置为进度百分比并从主线程中的计时器读取。请记住,UI 组件不是线程安全的,因此只能从单个线程更新。
Q2。我也看到了。与英迪无关。我认为,当您将状态栏设置为 100% 时,组件不会立即响应,而是会尝试平稳地移动到该点(但没有时间)。不过,这只是一个猜测。我不知道。或者它可能是我猜的防冻剂处理消息的频率(在这种情况下它与 Indy 有关)。
Q3。真的和Q1一样,解决方法一样。放入一个单独的线程并从主线程监视该线程的状态。
一旦您将 Indy 操作移至单独的线程,您就不需要 Antifreeze。
关于Q1和Q2,一个线程当然更好。如果您决定继续使用 Indy Antifreeze,您应该确保将 OnlyWhenIdle 标志设置为 False,以便它可以在工作完成时处理消息。
- Q1:为什么下载过程中模态窗体无法关闭
- Q2:为什么下载完成后进度条不是100%丰富(重绘的一种方式?)
- 问题 3:为什么我在运行期间停止并重新启动与 Web 服务器的连接? 下载传输正在停止而不显示任何错误并且 永不继续?我该怎么做才能得到并捕获错误然后去 回到初始状态(下载安装进度条在 位置 0)
备注:IdAntiFreeze 已激活
procedure Tform_update.button_downloadClick(Sender: TObject);
var
FS: TFileStream;
url, file_name: String;
begin
//execute download
if button_download.Tag = 0 then
begin
Fdone:= False;
Fcancel:= False;
url:= APP_DOMAIN + '/downloads/Setup.exe';
file_name:= 'C:\Temp\Setup.exe';
if FileExists(file_name) then DeleteFile(file_name);
try
FS:= TFileStream.Create(file_name, fmCreate);
Http:= TIdHTTP.Create(nil);
Http.OnWorkBegin:= HttpWorkBegin;
Http.OnWork:= HttpWork;
Http.Get(url, FS);
finally
FS.Free;
Http.Free;
if Fdone then ModalResult:= mrOk;
end;
end
else
//cancel download
begin
Fcancel:= True;
end;
end;
procedure Tform_update.HttpWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
ContentLength: Int64;
Percent: Integer;
begin
ContentLength:= Http.Response.ContentLength;
if AWorkCount = ContentLength then Fdone:= True; //
if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and (ContentLength > 0) then
begin
sleep(15);
Percent := 100 * AWorkCount div ContentLength;
progress_bar.Position:= Percent;
end;
//stop download
if Fcancel and Http.Connected then
begin
Http.IOHandler.InputBuffer.Clear;
Http.Disconnect;
Fcancel:= False;
button_download.Caption:= _('Download and Install');
button_download.Tag:= 0;
progress_bar.Position:= 0;
end;
end;
procedure Tform_update.HttpWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
if AWorkMode <> wmRead then Exit;
button_download.Tag:= 1;
button_download.Caption:= _('Cancel');
end;
procedure Tform_update.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Fcancel:= True;
end;
另一种方法是使用TThread 来控制执行。像这样:
ThreadUpdate = class(TThread)
protected
procedure Execute; override;
public
procedure ThreadUpdate.Execute;
begin
inherited;
while (not terminated) do
begin
//YOUR CODE HERE - maybe your button_download Click
Terminate;
end;
end;
您也可以尝试让 Windows 为您的应用程序处理消息。
if (Pos('chunked', LowerCase(Http.Response.TransferEncoding)) = 0) and (ContentLength > 0) then
begin
sleep(15);
Percent := 100 * AWorkCount div ContentLength;
progress_bar.Position:= Percent;
**Application.ProcessMessages;**
end;
Q1。 Indy 正在阻止。 All Antifreeze 会定期调用 windows 消息处理。它不会阻止 Indy 的阻塞性质,因此除非您明确地有一种方法来处理错误,否则它不会按照您想要的方式运行。您需要在不同的线程中进行下载并使用您的表单来监视该线程的状态,而不是尝试依赖防冻剂。不要在该线程中放置任何 UI 操作,将它们留在主线程中,因此不要尝试从线程内更新进度条。例如,将同步变量设置为进度百分比并从主线程中的计时器读取。请记住,UI 组件不是线程安全的,因此只能从单个线程更新。
Q2。我也看到了。与英迪无关。我认为,当您将状态栏设置为 100% 时,组件不会立即响应,而是会尝试平稳地移动到该点(但没有时间)。不过,这只是一个猜测。我不知道。或者它可能是我猜的防冻剂处理消息的频率(在这种情况下它与 Indy 有关)。
Q3。真的和Q1一样,解决方法一样。放入一个单独的线程并从主线程监视该线程的状态。
一旦您将 Indy 操作移至单独的线程,您就不需要 Antifreeze。
关于Q1和Q2,一个线程当然更好。如果您决定继续使用 Indy Antifreeze,您应该确保将 OnlyWhenIdle 标志设置为 False,以便它可以在工作完成时处理消息。