Delphi 中检查非暂停创建的 TThread 且 FreeOnTerminate = True 是否仍在执行的正确方法是什么?

What's the correct way in Delphi to check if a non-Suspended created TThread with FreeOnTerminate = True is still executing?

所以我创建了一个class:TWorkerThread = class(TThread)。在 TWorkerThread 构造函数中,我设置了 FreeOnTerminate := True.

然后我向 TForm 添加了一个私有 Worker 变量。当我为 Worker 实例化 TWorkerThread 时,我总是使用 CreateSuspended := False.

一旦启动,我需要与线程进行的唯一交互是取消进程 (Terminate) 并检查进程是否结束(该检查基于用户事件)。

要检查线程是否仍处于活动状态,我会这样做:

if (Self.Worker <> nil) and (not Self.Worker.Finished) then
    //Still active

这似乎工作正常但我担心 TWorkerThread 有时会是 <> nil 但仍然是 .free(记住 TWorkerThread 都是 FreeOnTerminate := True).当TWorkerThread“自我毁灭”一旦终止,它们总是会变成nil吗?如果不是,我该如何处理(以避免访问冲突)?

另一件事,如果 Worker 在其形式销毁时处于活动状态,我会:

if (Self.Worker <> nil) and (not Self.Worker.Finished) then
begin
    Self.Worker.Terminate;
    //wait here for completion
end;

Terminate 之后,如果我执行 WaitFor 我会遇到访问冲突(因为自毁)。我应该在这里强制等待吗?最好的方法是什么?

这是我在 Delphi 中第一次正确使用 TThread。为清楚起见,上面的代码是我所做内容的略读版本。

What's the correct way in Delphi to check if a non-Suspended created TThread with FreeOnTerminate = True is still executing?

有none.

一旦启动自毁线程,您就不能再从外部代码中访问持有此类线程的引用,因为该引用随时可能变得陈旧。

在某些情况下(如果 DoTerminate 中的逻辑处理 OnTerminate 调用未在您的自定义线程 class 中修改)您可以安全地从 OnTerminate 事件访问线程引用处理程序。但是,这不会帮助您解决问题,因为您不能等待自毁线程。在 Windows 上,此类代码会导致可以捕获和处理的异常,但在其他平台上,它会导致未定义的行为和随机死锁。但即使 Windows 编写这样的代码也是不可取的。

如果你需要检查一个线程的状态,取消它或等待它,你不能使用自毁线程。时期。 (对于那些可能反对先前声明的人,是的,在某些情况下,其中一些事情是可能的,但它们通常会导致搬起石头砸自己的脚)。

您可以将以下工作流程与 TWorkerThread 一起使用,前提是您在线程构造函数中将 FreeOnTerminate 保留在 False 上并构造未挂起的线程。必须从主线程调用以下所有方法以避免 Worker 引用上的竞争条件。在您的表单打开时有一个不执行任何操作的额外线程不会给您带来任何麻烦。

procedure TMyForm.StartWorker;
begin
  FreeAndNil(Worker); // or if Assigned(Worker) then Exit;
  Worker := TWorkerThread.Create;
end;

procedure TMyForm.CancelWorker;
begin
  // this will initiate thread termination and waiting
  FreeAndNil(Worker);
end;

procedure TMyForm.Destroy;
begin
  // technically we could only use Free here, 
  // but since other code requires niling the reference this is more consistent 
  FreeAndNil(Worker);
  inherited;
end;