【问题标题】:Delphi: Issues during download of update file, with Indy (TidHttp)Delphi:下载更新文件时出现问题,使用 Indy (TidHttp)
【发布时间】:2015-07-16 13:17:41
【问题描述】:
  • Q1:为什么在下载过程中无法关闭模态表单
  • Q2:为什么下载完成后进度条没有100%丰富(是重绘的一种方式?)
  • Q3:为什么如果我停止并重新启动与 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;

【问题讨论】:

  • 您显然错过了这个网站的运作方式。这是一个问答网站(单数),而不是Multiple Questions and Answers(复数)。帖子应包含一个问题。如果您有多个帖子,请创建单独的帖子;您可以随时链接回一个或多个其他人以提供参考资料。
  • 感谢大家的快速回复!所有答案都有帮助。我会用线程来做。 @KenWhite 我会记住下一个问题。

标签: delphi download indy idhttp


【解决方案1】:

第一季度。印地堵住了。所有 Antifreeze 都会定期调用 Windows 消息处理。它不会阻止 Indy 的阻塞特性,因此除非您明确有办法处理错误,否则它不会按照您的意愿行事。您需要在不同的线程中进行下载并使用您的表单来监控该线程的状态,而不是尝试依赖防冻剂。不要在该线程中放置任何 UI 操作,将它们留在主线程中,因此不要尝试从线程内更新进度条。例如,将同步变量设置为进度百分比,并从主线程中的计时器中读取。请记住,UI 组件不是线程安全的,因此只能从单个线程更新。

第二季度。我也看到了。与印地无关。我认为当您将状态栏设置为 100% 时,组件不会立即响应,而是尝试平稳移动到该点(但没有时间)。不过,这只是一个猜测。我不确定。或者可能是我猜想防冻剂处理消息的频率(在这种情况下,它与 Indy 有关)。

第三季度。真的和Q1一样,解决方法一样。放入一个单独的线程,并从主线程监控该线程的状态。

一旦您将 Indy 操作移至单独的线程,您就不需要 Antifreeze。

【讨论】:

    【解决方案2】:

    另一种方法是使用 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;
    

    【讨论】:

    • 这个答案充其量是基本的。例如,当涉及到来自非 UI 线程的 UI 访问时,必须考虑线程安全。
    【解决方案3】:

    关于 Q1 和 Q2,线程肯定更好。如果您决定继续使用 Indy Antifreeze,则应确保将 OnlyWhenIdle 标志设置为 False,以便它可以在工作完成时处理消息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 1970-01-01
      • 2017-07-08
      • 2013-07-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多