TThread.CreateAnonymousthread / FreeOnTerminate 然后使用 TTask / ITask

问题描述

背景

使用 TThread.CreateANonymousThread(aProc:TProc) 我可以创建一个线程,在线程终止后销毁线程对象。 (或者,对于线程对象,将 FreeOnTerminate 设置为 true)。这允许线程启动器例程完成并超出范围,而线程继续运行。 (这就是我要找的)

procedure StartProcess
begin

  var lTask:=TThread.CreateAnonymousThread(
    procedure
    begin
       ... Do lengthy thread stuff here 
    end
    );
  ...
  lTask.Start;
end;

问题出现了,TTask.Create 返回一个 ITask 接口,当线程发起者代码删除其上下文(RefCount 下降到 0 -> {{1} } 被调用),导致线程生成一个 AV。

Destroy

procedure StartProcess begin var lTask:=TTask.Create( procedure begin ... Do lengthy thread stuff here end ); ... lTask.Start; end; /// past this point,the subthread wil crash because the underlying task object is destroyed 的情况下,我们有一个名为 OmniThread解决方案,可避免任务对象在完成之前被销毁。

为什么?

编辑:我喜欢 IOmniTaskCOntrol.Unobserved 类上的 ITask 接口,因为它允许松散耦合和代码注入。 (上一篇:因为 TThread 可能会被弃用:别提了)

问题

我想知道是否(以及如何!)使用 TThreadTTask.Create(aProc:TProc) 接口可以实现相同的效果。到目前为止,分析源代码对我没有帮助。

解决方法

答案很简单:您无需做任何特别的事情ITask 调用返回的 TTask.Create 接口也在内部由 InternalExecute 方法“保留”,因此底层 TTask 对象将通过引用计数销毁。如果“主”线程不持有 ITask 接口,子线程。直到它终止。

因此以这种方式使用 TTask 非常简单。

注意:在 RS10.4.2 中这是有效的,我怀疑使用捕获的接口变量可能会在 10.4.1 及更早版本中导致问题,因为内联 var 问题与匿名过程相结合。 (没试过)