我在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;
答案 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)
正如人们正确指出的那样,你不应该打电话给#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章。