I'm facing a problem in an application I've developed. It is an automatic updater that basically downloads the necessary files and extracts them in a suitable way. The problem is time to download. I put the download method inside a Thread, put it inside the Syncronize, however it "hangs", does not let me move the window (interface) until the process finishes. Remember that when downloading it calls the method that changes the progress bar.
In another case, I only put the method that changes the loading bar inside the syncronize, causing the window to not be locked anymore, I can move it while the download is done, however the rest of the code is 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 finish, does this thread complete before proceeding with the code execution? Because if I continue it will give an error in the application because it does not have the file, because the file is still being downloaded.
Calling the download method inside 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 inside 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 on the main form (uFrmPrincipal.pas)
procedure TfrmAtualizador.UpdateProgressBar(aProgress, Total: Int64);
begin
gProgresso.MaxValue := Total;
gProgresso.Progress := aProgress;
gProgresso.Update;
end;
Class 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.