【问题标题】:Why can't I call CheckTerminated on an externally created thread?为什么我不能在外部创建的线程上调用 CheckTerminated?
【发布时间】:2019-08-09 17:17:20
【问题描述】:

当我运行这段代码时:

  FMyThread := TThread.createAnonymousThread(
   procedure
   begin
     while not FMyThread.CheckTerminated do begin
       sleep(750);
       TThread.synchronize(nil,
         procedure
         begin
           if FMyThread.CheckTerminated then exit;
           ....
         end);
     end;
   end);
   FMyThread.start;

我有例外

无法在外部创建的线程上调用 CheckTerminated

为什么?

【问题讨论】:

  • 查看this页面,我想对你有帮助
  • 附带说明,保留对匿名线程的引用并期望使用它是非常危险的。一旦你启动它,它就毫无意义,因为线程可能会在你想使用它的时候终止。相反,只需在一次通话中使用TThread.CreateAnonymousThread( ... ).Start;
  • 我怀疑这里有误会。当您调用 CheckTerminated 时,您的目标是什么?
  • 简单的解决方案是不要从 Synchronize 中依赖它,它应该只有最少的代码和非常短的执行时间。毕竟,这首先是线程背后的主要思想,以保持主线程响应。如果您担心线程在Synchronize 中终止,那么您需要重新考虑您的设计。此类检查应在实际线程本身的上下文中进行,而不是在Synchronize(主线程)中进行。就个人而言,我认为任何人都希望在 Synchronize 中获取此信息的原因为零。

标签: delphi delphi-xe2


【解决方案1】:

如果你查看 CheckTerminated 的实现,你会发现它不是一个方法,而是一个静态类方法。

CheckTerminated 指示当前执行的线程是否将其Terminated 标志设置为TRUE。当您在 TThread.synchronize 中调用 FMyThread.CheckTerminated 时,它不会检查 FMyThread.Terminated,它会尝试检查“GetCurrentThreadId”的状态,在这种情况下,它是您进程的主线程。

由于主线程不是由 TThread 创建的,因此 RTL 会创建一个 TExternalThread(参见 class function TThread.GetCurrentThread: TThread

换句话说,如果你有一个 TThread 对象并想检查它是否被终止,你应该调用Terminated,而不是CheckTerminated

由于 AnonymousThread 默认在终止时被释放,因此您需要确保在 OnTerminate 处理程序中清除对您的线程的任何引用。

【讨论】:

  • 但终止受 XE2 保护,我无法访问它:(
  • @Stephane 您在问题中没有提到 XE2。我已经为你添加了标签。根据经验,如果问题没有特定版本,则假定它是最新的当前版本。最好只创建一个继承的 TThread 对象。特别是如果您打算让它执行任何类型的长时间运行的任务。
  • @Stephane 您可以使用访问器类从类外部访问类的受保护成员,例如type TThreadAccess = class(TThread) end; ... if TThreadAccess(FMyThread).Terminated then ...
  • @Stephen 我也这么想。 CheckTerminated 不会像您认为的那样做。您的问题的解决方案不涉及调用 CheckTerminated。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 2014-03-20
  • 1970-01-01
相关资源
最近更新 更多