2
I’m facing a problem in an application that I developed. It is an automatic updater that basically downloads the necessary files and extracts them in a suitable path. The problem is time to download. I put the download method inside a Thread, I put it inside Syncronize, but it "hangs", does not let me move the window(interface) until the process is over. Remembering that when downloading it calls the method that changes the progress bar.
In another case, I put only the method that changes the loading bar inside the syncronize, making the window no longer locked, I can move it while the download is done, but all the rest of the code runs and this can not happen in my case, because I depend on the file being downloaded to continue.
The final question is, how do I wait for this download to end, this Thread to finish, before proceeding with the execution of the code? Because if I proceed it will give error in the application for not having the file, as it is still being downloaded.
Call the download method within the main form (uFrmPrincipal.pas)
ThreadBaixarAtualização('c:\caminho\atua_beta',
'http://www.site.com.br/atualizacao/atua_beta.zip', true);
ThreadBaixarAtualização('c:\caminho\scripts',
'http://www.site.com.br/atualizacao/scripts.zip', False);
Method to create the Thread instance within the Main Form (uFrmPrincipal.pas)
procedure TfrmAtualizador.ThreadBaixarAtualização(CaminhoNomeArquivo,
URL: String; Status: Boolean);
begin
FConHTTPThread := TConHTTPThread.create(true, UpdateProgressBar);
FConHTTPThread.FreeOnTerminate := true;
FConHTTPThread.URL := URL;
FConHTTPThread.CaminhoNomeArquivo := CaminhoNomeArquivo;
FConHTTPThread.Status := Status;
FConHTTPThread.Start;
end;
Method that changes the progress bar in the main form (uFrmPrincipal.pas)
procedure TfrmAtualizador.UpdateProgressBar(aProgress, Total: Int64);
begin
gProgresso.MaxValue := Total;
gProgresso.Progress := aProgress;
gProgresso.Update;
end;
Class(Unit) to download the files - Separate Unit(uConHTTPThread.pas)
unit uConHTTPThread;
interface
uses
System.Classes, SysUtils, Forms, IdHTTP, IdComponent,
Vcl.Dialogs, System.UITypes;
type
// Tipo que contem um método com os mesmos parâmetros que a barra de progresso
// do formulario principal
TBarraProgress = procedure(aProgress, Total: Int64) of object;
TConHTTPThread = class(TThread)
procedure IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Int64);
procedure IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
AWorkCountMax: Int64);
procedure IdHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
private
FIdHTTP1: TIdHTTP;
FValorMaximo: Int64;
FProgresso: Int64;
FfileDownload: TFileStream;
FCaminhoNomeArquivo, FURL: String;
FStatus: Boolean;
FBarraProgress: TBarraProgress;
procedure SetCaminhoNomeArquivo(const Value: String);
procedure SetURL(const Value: String);
procedure SetStatus(const Value: Boolean);
procedure AtualizaBarra;
protected
procedure Execute; override;
procedure BaixarAtualizacao;
procedure Progress(aProgress: Int64); virtual;
Public
property Progresso: Int64 read FProgresso;
property Total: Int64 read FValorMaximo;
property CaminhoNomeArquivo: String read FCaminhoNomeArquivo
write SetCaminhoNomeArquivo;
property URL: String read FURL write SetURL;
property Status: Boolean read FStatus write SetStatus;
constructor Create(CreateSuspended: Boolean;
pBarraProgress: TBarraProgress); reintroduce; virtual;
end;
implementation
// Responsável por efetuar o Donwload dos arquivos de atualização
procedure TConHTTPThread.BaixarAtualizacao;
begin
try
if not Assigned(FIdHTTP1) then
FIdHTTP1 := TIdHTTP.Create(Nil);
FfileDownload := TFileStream.Create(FCaminhoNomeArquivo +
ExtractFileExt(FURL), fmCreate);
if Status = True then
begin
with FIdHTTP1 do
begin
OnWork := IdHTTP1Work;
OnWorkBegin := IdHTTP1WorkBegin;
end;
end;
FIdHTTP1.Get(FURL, FfileDownload);
finally
if Assigned(FIdHTTP1) then
FreeAndNil(FIdHTTP1);
if Assigned(FfileDownload) then
FreeAndNil(FfileDownload);
end;
end;
constructor TConHTTPThread.Create(CreateSuspended: Boolean;
pBarraProgress: TBarraProgress);
begin
inherited Create(CreateSuspended);
FBarraProgress := pBarraProgress;
end;
procedure TConHTTPThread.Execute;
begin
if (not Terminated) then
begin
Sleep(10);
Synchronize(BaixarAtualizacao);
end;
end;
procedure TConHTTPThread.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Int64);
begin
Progress(AWorkCount);
end;
procedure TConHTTPThread.IdHTTP1WorkBegin(ASender: TObject;
AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
// Verifica tamanho total do arquivo a ser baixado
FValorMaximo := AWorkCountMax;
end;
procedure TConHTTPThread.IdHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
FValorMaximo := FValorMaximo;
end;
procedure TConHTTPThread.Progress(aProgress: Int64);
begin
FProgresso := aProgress;
AtualizaBarra;
end;
procedure TConHTTPThread.SetCaminhoNomeArquivo(const Value: String);
begin
FCaminhoNomeArquivo := Value;
end;
procedure TConHTTPThread.SetStatus(const Value: Boolean);
begin
FStatus := Value;
end;
procedure TConHTTPThread.SetURL(const Value: String);
begin
FURL := Value;
end;
procedure TConHTTPThread.AtualizaBarra;
begin
// Atualiza barra de progresso no formulário principal
if Assigned(FBarraProgress) then
FBarraProgress(FProgresso, FValorMaximo);
end;
end.
I get it. I’m going to work on that idea. Thank you.
– Cayque Duarte
Okay, anything I’m up for.
– Marcelolx