QThread :: quit()会立即结束线程还是等到返回事件循环?

时间:2014-05-28 23:13:48

标签: c++ multithreading qt

有很多Qt多线程教程说明可以使用以下两行安全地停止QThread

qthread.quit(); // Cause the thread to cease.
qthread.wait(); // Wait until the thread actually stops to synchronize.

我有很多代码在执行此操作,并且在大多数情况下停止线程,我将始终设置自己的取消标志并在执行期间经常检查它(这是常态)。到目前为止,我认为调用quit可能会导致线程不再执行任何等待信号(例如,排队的信号将不再调用其槽),但仍然等待当前正在执行的槽完成。

但是我想知道我是对的,还是quit()实际上停止了它所处的线程的执行,例如,如果某些事情未完成,就像文件描述符尚未关闭一样,它肯定应该即使在大多数情况下,我的工作对象会清理这些资源,但如果我确切知道戒烟是如何工作的,我会感觉更好。

我问这个是因为QThread::quit()文档说它“相当于调用QThread :: exit(0)”。我相信这意味着线程会立即停在它所在的位置。但是在调用退出的堆栈框架中会发生什么?

2 个答案:

答案 0 :(得分:8)

如果线程没有事件循环或线程中的某些代码阻塞事件循环,则

QThread::quit不执行任何操作。所以它不一定会阻止线程。

所以QThread::quit告诉线程的事件循环退出。调用它之后,一旦控件返回到线程的事件循环,线程就会完成。

如果您阻止事件循环,例如通过循环工作,则必须添加某种中止标志。这可以通过公共成员变量来完成,或者至少具有公共setter方法。然后你可以通过设置中止标志告诉线程从外面(例如从你的主线程)退出ASAP。当然,这将要求您的线程代码定期检查中止标志。

您也可以通过QThread::terminate()强制线程立即终止,但这是一种非常糟糕的做法,因为它可能会在其代码中的未定义位置终止该线程,这意味着您可能最终获得资源永远不会被释放和其他令人讨厌的东西。所以只有在你真的无法绕过它时才使用它。从其文档:

  

警告:此功能很危险,不建议使用它。线程可以在其代码路径中的任何位置终止。修改数据时可以终止线程。线程无法自行清理,解锁任何保持的互斥锁等。简而言之,只有在绝对必要时才使用此功能。

我认为这是在线程中使用循环时完成线程的好方法:

myThread->m_abort = true; //Tell the thread to abort
if(!myThread->wait(5000)) //Wait until it actually has terminated (max. 5 sec)
{
  myThread->terminate(); //Thread didn't exit in time, probably deadlocked, terminate it!
  myThread->wait(); //We have to wait again here!
}

答案 1 :(得分:0)

如果要使用Qt的内置功能,请尝试QThread::requestInterruption()

主线程

struct X {
  QThread m_Thread; 
  void Quit ()
  {
    m_Thread.quit();
    m_Thread.requestInterruption();
  }
};

X::m_Thread引用的某些线程

while(<condition>) {
  if(QThread::currentThread()->isInterruptionRequested())
    return;
  ...
}

根据文档:

  

void QThread :: requestInterruption()

     

请求中断线程。该请求是建议性的,并且由线程上运行的代码决定是否以及如何应此类请求执行。此功能不会停止线程上运行的任何事件循环,也不会以任何方式终止它。