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;
所以我创建了一个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;