TThread.CreateAnonymousthread / FreeOnTerminate 但随后使用 TTask / ITask

TThread.CreateAnonymousthread / FreeOnTerminate but then with 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 returns 一个 ITask 接口,当线程启动器代码删除它的上下文时(RefCount 下降到 0 -> Destroy 被调用),导致线程生成 AV。

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 class,因为它允许松耦合和代码注入。 (prev: 因为 TThread 可能会被弃用: 忘了吧)

问题

我想知道是否(以及如何!)使用 TTask.Create(aProc:TProc)ITask 界面可以完成相同的任务。到目前为止,分析源代码对我没有帮助。

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

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

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