当你终止一个线程(TThread类),它是否会退出该线程的每个子线程?

5

我有一个Delphi代码,它可以执行以下操作:

procedure THilo.Execute; // (which is the thread)
begin
  inherited;
  FreeOnTerminate := True;
  while not Terminated do
  begin
    (...)
    Sleep(100);
  end;
end;

现在在另一个线程(或GUI)中,我们做了这个:

var
  Hilo2: THilo;
begin
  Hilo2 := THilo.Create(True);
  Hilo2.start;
  Hilo2 := THilo.Create(True);
  Hilo2.start;
end;

现在我们已经执行了两次相同的线程,它们正在并行运行。如果我们现在这样做会发生什么呢?

  Hilo2.Terminate;

这会同时终止两个线程还是只有一个?如果我们想要终止它,能通过 .Resume() 实现吗?

提前感谢。

1个回答

8
当您创建第二个线程时,您正在用指向第二个对象的指针覆盖局部变量 Hilo2 - 第一个对象的指针丢失了,您不再有任何对它的引用(或控制方式)。如果线程没有自行终止,则会导致内存泄漏,而且,不,调用 terminate 不会停止两个线程,只会停止最后使用该变量作为引用创建的线程。此外,在 TThread 的 Execute 方法中调用 inherited 是没有必要的 - 没有什么需要继承的(TThread 的 execute 方法是抽象的,它什么也不做)。

谢谢 J, 我的程序里有这个问题,我无法终止线程。所以只需要一个 TThread 的数组就可以解决了,对吗?像这样:Hilo[i] := THilo.Create(True); Hilo[i].start; - user2308704
1
哦,又来了一个熟练的 Delphi 多线程开发者。这样至少有两个人了 :) - Martin James
3
同时,由于使用了 FreeOnTerminate=True,如果线程意外终止(未捕获的异常等),那么如果线程已经消失,则调用 Terminate() 可能会失败(或更糟糕的是,导致内存损坏)。FreeOnTerminate=True 应该只用于创建并忘记的线程。一旦你必须因为 任何原因(挂起/恢复、终止/等待、更新/访问成员等)外部触摸一个线程,就不要使用 FreeOnTerminate=True - Remy Lebeau
@user2308704 一个数组可以解决问题 - 无论如何,您需要保留对每个创建的线程的引用。 - J...
4
另一个需要注意的地方- 如果您要使用 FreeOnTerminate=True,请在构造函数中设置它(或至少在 ACreateSuspended=True 时调用 Resume/Start()之前)。这是因为几年前,更新了 TThread,如果在线程实际开始运行之前调用 Terminate(),则根本不会调用 Execute()。如果 Execute() 设置了 FreeOnTerminate=True,则可能会导致内存泄漏。 - Remy Lebeau
7
停止如此傲慢。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接