Delphi中的线程问题

时间:2011-08-01 10:14:58

标签: multithreading delphi md5

我在Delphi中遇到线程问题。当使用TIdHashMessageDigest5从大文件中获取MD5时,我注意到它需要花费太多时间,并最终导致应用程序冻结。

我正在考虑使用单独的线程。所以我做了一个小形式,我在样式pbstMarquee中插入一个简单的消息,一个按钮和一个进度条。我在这个表单的show事件上开始一个线程。

我的问题是:我想在HashStreamAsHex成功完成阅读时关闭此表单,但是我该怎么办呢?我尝试在同步时调用Close方法,但随后关闭表单而不等待该线程完成。我也尝试使用waitfor方法,但没有成功。

有人可以帮我这个,给我一些例子,或链接或类似?

非常感谢,抱歉我的英语不好。

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;

5 个答案:

答案 0 :(得分:3)

没有人指出这一点,在函数内部没有返回任何值。

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;

答案 1 :(得分:1)

在您发布的代码中,Self.WaitFor将永远不会返回。等待线程终止,即其Execute方法已完成。但这不可能发生,因为它停止并等待自己。您只需删除对WaitFor的通话即可。

我也想知道Close是否是终止表单的正确方法。如果它确实是模态形式,那么您应该使用oForm.ModalResult := mrOK


我刚刚看到您的编辑内容包含GetFileMD5的定义。此函数不返回值。你应该收到一个编译器警告告诉你这个 - 读取编译器警告,它们非常有价值。像这样写GetFileMD5

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;

答案 2 :(得分:1)

关于WaitFor

正如人们正确指出的那样,你不应该打电话给#34; Self.WaitFor;"。

WaitFor旨在从其他线程调用。线程可能不会等待自己 - 这与逻辑相反。例如,我不能等待自己 - 我总是为自己做好准备! ;-)所以是线程。

从线程关闭表单的最佳方法

关闭表单的最佳方法是使用PostMessage向其窗口句柄发送WM_CLOSE消息。

而不是"同步(DoSync);"执行以下操作:" PostMessage(FormProgress.Handle,WM_CLOSE,0,0);"。

这里的FormProgress是varable,它包含指向TFormProgress类实例的指针。因此," DoSync"不需要。

开启同步

作为一项规则,"同步"表明应用程序设计有些不好。在没有任何同步的情况下设计应用程序会更好。

答案 3 :(得分:0)

我的猜测:表单以模态模式(form.ShowModal)打开,并且在计算完成之前有一些东西可以指定form.ModalResult。   这将导致istantaneus关闭表单。

也许你放置了一个TBalButton,其modalresult属性设置为mrOk?如果你这样做了,只要有一个正在运行的线程,只要onClick事件处理程序终止,按下该按钮就会关闭表单。

答案 4 :(得分:0)

This is是一个很好的文档,关于delphi中的线程,有示例,情况。从头开始阅读,我相信你会自己找到答案。你不必阅读所有内容,只需要阅读前4-5章。