Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with threads in Delphi

I have a problem with threads in Delphi. When using TIdHashMessageDigest5 in order to get MD5 from a big file, I have noticed that it takes too much time, and ends up in an application freeze.

I'm thinking about using a separate thread. So I have made a little form where I insert a simple message, a button and a progress bar in style pbstMarquee. I start a thread on the show event of this form.

My problem is: I want to close this form when HashStreamAsHex has finished reading successfully, but how can I do this? I tried calling the Close method on synchronize, but then the form is closed without waiting for that thread to finish. I also tried to use the waitfor method, without success.

Someone can help me with this, giving me some example, or link or similar?

Thanks very much and sorry for my bad english.

About form:
-----------
procedure TFormProgress.FormProgressOnShow(Sender: TObject);
begin
  ProgressThread := TProgressThread.Create(True);
  ProgressThread.Form := FormProgress;
  ProgressThread.FileSrc := uFileSrc;
  ProgressThread.Start;
end;

About thread:
-------------
procedure TProgressThread.Execute;
begin
  FreeOnTerminate := True;
  uFileMD5 := GetFileMd5 (uFileSrc)  // function is definited in other unit.
  Self.WaitFor;
  Synchronize(DoSync);
end;

procedure TProgressThread.DoSync;
begin
  oForm.Close;
end;

GetFileMd5 è so defined:

function GetFileMD5(const Src: TFileName): UnicodeString;
var
  Md5: TIdHashMessageDigest5;
  FileSrc: TFileStream;
  StrMd5: UnicodeString;
begin
  Md5 := TIdHashMessageDigest5.Create;
  try
    FileSrc := TFileStream.Create(Src, fmOpenRead);
    try
      StrMd5 := Md5.HashStreamAsHex(FileSrc);
    finally
      FileSrc.Free;
    end;
  finally
    Md5.Free;
  end;
end;
like image 839
Marcello Impastato Avatar asked Aug 01 '11 10:08

Marcello Impastato


3 Answers

No one has pointed this out, inside the function no value was returned.

function GetFileMD5(const Src: TFileName): UnicodeString;
var
  Md5: TIdHashMessageDigest5;
  FileSrc: TFileStream;
  StrMd5: UnicodeString;
begin
  Md5 := TIdHashMessageDigest5.Create;
  try
    FileSrc := TFileStream.Create(Src, fmOpenRead);
    try
      StrMd5 := Md5.HashStreamAsHex(FileSrc);
    finally
      FileSrc.Free;
    end;
  finally
    Md5.Free;
  end;
  // You are missing this line, calculated md5 was never returned
  Result := StrMd5;
end;
like image 87
Darkerstar Avatar answered Nov 14 '22 20:11

Darkerstar


In the code you posted, Self.WaitFor will never return. That waits until the thread has terminated, i.e. its Execute method has completed. But that can't happen because it stops and waits for itself. You should simply remove the call to WaitFor.

I also wonder whether or not Close is the correct way to terminate the form. If it really is a modal form then you should use oForm.ModalResult := mrOK.


I've just seen your edit which includes the definition of GetFileMD5. This function doesn't return a value. You should receive a compiler warning telling you of this—read the compiler warnings, they are very valuable. Write GetFileMD5 like this:

function GetFileMD5(const Src: TFileName): string;
var
  Md5: TIdHashMessageDigest5;
  FileSrc: TFileStream;
begin
  Md5 := TIdHashMessageDigest5.Create;
  try
    FileSrc := TFileStream.Create(Src, fmOpenRead);
    try
      Result := Md5.HashStreamAsHex(FileSrc);
    finally
      FileSrc.Free;
    end;
  finally
    Md5.Free;
  end;
end;
like image 2
David Heffernan Avatar answered Nov 14 '22 21:11

David Heffernan


My guess: the form is opened in Modal mode (form.ShowModal) and there is something that assigns the form.ModalResult before the calculation has completed. This would cause the istantaneus closing of the form.

Maybe did you place a TBitButton having the modalresult propery set to mrOk? if you have done so, pressing that button will close the form as soon as the onClick event handler terminates, no matter if there is a running thread.

like image 1
Carlo Sirna Avatar answered Nov 14 '22 22:11

Carlo Sirna