首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >销毁TThread对象的正确方法

销毁TThread对象的正确方法
EN

Stack Overflow用户
提问于 2009-07-06 22:21:42
回答 2查看 12K关注 0票数 16

这个问题可能看起来微不足道,但我希望您不要忽视它。

在销毁TThread对象之前,通常需要等待调用TThread.Execute()方法的线程完成,因为只有在那时我们才能确定,例如,在类的析构函数内销毁的对象不再被访问。因此,有必要调用Terminate来设置终止标志,线程必须检查该标志才能知道是否退出,然后调用WaitFor()方法。

因为线程可能被挂起,所以我认为在调用WaitFor之前恢复它是很好的,否则调用线程将会死锁。因为线程可以挂起多次,所以它应该恢复相同的次数,对吧?

代码语言:javascript
复制
while Suspended do
  Resume;

如果线程是被挂起创建的,我们不必担心当我们恢复线程只是为了终止它时,TThread.Execute()方法会被调用-它不会(如果我错了,请纠正我)。

我所说的建议对每个被释放的TThread对象使用以下代码行:

代码语言:javascript
复制
MyThread.Terminate;
while MyThread.Suspended do
  MyThread.Resume;
MyThread.WaitFor;
MyThread.Free;

不幸的是,当我们销毁创建了多个线程的应用程序时,为每个被销毁的TThread对象编写这样的代码会使代码变得非常长,甚至可能是不透明的。

因此,我得出的结论是,所有这些都可以放在TThread类的重写析构函数中,这要归功于调用MyThread.Free (如果设置了MyThread.FreeOnTerminate,则调用MyThread.Terminate )就足够了,而不必关心被销毁的对象是否是TThread对象:

代码语言:javascript
复制
destructor TMyThread.Destroy;
begin
  //if FreeOnTerminate, the calling thread cannot wait for itself
  if GetCurrentThreadId <> ThreadId then
  begin
    Terminate;
    while Suspended do
      Resume;
    WaitFor;
  end;

  {free all objects created in this class}

  inherited Destroy;
end;

请原谅我问了这么基本的问题。但是,我想了解您对这种销毁TThread对象的方式的看法--我希望是一种通用的方式。我问这个问题是因为我从同事的代码中了解到,他们通常使用代码的第一个示例来销毁这些对象,但他们从不检查正在等待的线程是否没有挂起,我认为如果线程可能在代码中的某个地方挂起,这是有点危险的。因此,我试图找到一种通用的方法来销毁这个类的对象,这样可以使代码更清晰、更安全。我希望我没有让事情变得更糟--你觉得呢?

感谢您提前给我提建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-07-06 22:49:17

您所建议的大部分内容已经在TThread.Destroy析构函数中执行了,并且调用TMyThread.free将执行您所建议的操作。要清除thread类拥有的任何对象,可以在OnTerminate事件中执行该操作,该事件将作为线程关闭逻辑的一部分进行调用。

票数 8
EN

Stack Overflow用户

发布于 2009-07-07 14:57:23

没有通用的方法来停止线程,就像没有通用的方法来(优雅地)停止进程一样。每一个都是不同的。

对于某些线程,通过Terminate方法设置其Terminated属性就足够了。然而,其他线程调用诸如GetMessageMsgWaitForMultipleObjects之类的函数,这些函数将阻塞,直到发生某些事情,例如消息到达或内核句柄被通知为止。TThread.Terminate不能让这两件事发生,所以它不能让这些线程停止运行。当我编写了这样的线程时,我提供了自己的函数来通知它们停止运行。我可能会调用PostThreadMessage来强制将一条消息放到线程的队列中,或者我可能会通知事件线程类已经提供了终止请求的通知。

不要担心恢复挂起的线程。你真的不应该让他们停职。挂起线程的唯一安全方法是让线程挂起自己,一旦这样做了,您就可以保证至少有两个线程控制线程何时运行:线程本身挂起它,以及至少一个其他线程再次恢复它。线程应该控制自己的执行。

如果TThread.Terminate是虚拟的,那就太好了。然后,每个线程类都可以提供一种自定义方式来通知自己应该停止运行。一些人可以只设置Terminated,另一些人可以发布消息,通知事件,或者做任何他们需要的事情。但实际上,非虚方法并不能很好地处理那些花费大量时间等待其他事情的线程。目前的方法只适用于能够频繁轮询其Terminated属性的线程。

一些线程设置了它们的FreeOnTerminate属性。对于这些线程,您的代码是不安全的。从技术上讲,在这样的对象上调用任何方法都是不安全的,因为线程可能在任何时候终止。但是,即使您知道线程仍在运行,并且线程对象仍然存在,在调用Terminate之后的某个时间,该对象肯定会停止存在。不能在自由终止的线程对象上调用WaitFor,也绝对不能调用Free

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1089482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档