我的程序中有一个主线程和一个单独的线程。如果单独的线程在主线程之前完成,它应该自动释放自身。如果主线程先完成,它应该释放单独的线程。
我了解 FreeOnTerminate,并且我读到您必须小心使用它。
我的问题是,下面的代码正确吗?
procedure TMyThread.Execute;
begin
... Do some processing
Synchronize(ThreadFinished);
if Terminated then exit;
FreeOnTerminate := true;
end;
procedure TMyThread.ThreadFinished;
begin
MainForm.MyThreadReady := true;
end;
procedure TMainForm.Create;
begin
MyThreadReady := false;
MyThread := TMyThread.Create(false);
end;
procedure TMainForm.Close;
begin
if not MyThreadReady then
begin
MyThread.Terminate;
MyThread.WaitFor;
MyThread.Free;
end;
end;
最佳答案
您可以将其简化为:
procedure TMyThread.Execute;
begin
// ... Do some processing
end;
procedure TMainForm.Create;
begin
MyThread := TMyThread.Create(false);
end;
procedure TMainForm.Close;
begin
if Assigned(MyThread) then
MyThread.Terminate;
MyThread.Free;
end;
说明:
使用
FreeOnTerminate
或手动释放线程,但切勿同时执行这两种操作。线程执行的异步性质意味着您面临不释放线程或(更糟糕的是)执行两次的风险。在执行完成后保留线程对象没有风险,并且在已经完成的线程上调用Terminate()
也没有风险。无需同步对仅从一个线程写入并从另一个线程读取的 bool 值的访问。在最坏的情况下,您会得到错误的值,但由于异步执行,无论如何这是一个虚假的效果。仅对于无法原子读取或写入的数据才需要同步。如果您需要同步,请不要使用
Synchronize()
。不需要有类似于
MyThreadReady
的变量,因为您可以使用WaitForSingleObject()
询问线程的状态。将MyThread.Handle
作为第一个参数,将0
作为第二个参数传递给它,并检查结果是否为WAIT_OBJECT_0
- 如果是,则您的线程有执行完毕。
顺便说一句:不要使用 OnClose
事件,而是使用 OnDestroy
事件。前者不一定被调用,在这种情况下,您的线程可能会继续运行并使进程保持事件状态。
关于multithreading - 自动或手动释放 TThread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3557105/