QThread - 使用slot quit()退出线程

时间:2011-04-26 12:44:21

标签: c++ multithreading qt

我想在线程运行完毕后通知对象。但是,我无法让线程正常退出。我有以下代码:

Processor.cpp

thread = new QThread;
tw = new ThreadWorker;
connect(tw, SIGNAL(updateStatus(QString)), this, SLOT(statusUpdate(QString)));
tw->doSetup(thread, strDic);
tw->moveToThread(thread);
thread->start();

while(thread->isRunning())
{
}

qDebug() << "Thread Finished";

ThreadWorker.cpp

void ThreadWorker::doSetup(QThread *thread, const string &path)
{
  _strPath = path;
  connect(thread, SIGNAL(started()), this, SLOT(run()));
  connect(this, SIGNAL(finished()), thread, SLOT(quit())); //tried terminate() also
}


void ThreadWorker::run()
{
  DirectorySearch dicSearch;
  vector<string> vecFileList = dicSearch.getFileList(_strPath);
  emit updateStatus("Directory Fetched");
  emit finished();
}

quit()槽似乎没有停止线程(QThread :: isFinished永远不会返回true)。有人可以指导我朝正确的方向发展吗?

(注意:ThreadWorker不从QThread继承)

4 个答案:

答案 0 :(得分:4)

假设Processor.cpp正在主线程中运行,while(thread->isRunning())循环将主线程完全绑定。这意味着您的应用程序的事件循环无法执行任何处理,因此信号updateStatus()将永远不会被处理。正如评论中所提到的,由于QThread对象是由主线程创建的,因此它的信号也不起作用,因为它们也需要主事件循环来做它的事情。此外,如果您在主线程中等待工作线程执行某些操作,为什么要使用工作线程呢? :)

尝试删除while循环,将workDone()(或任何您想要调用的内容)添加到Processor.cpp并将其连接到Threadworker的{​​{1}}信号

答案 1 :(得分:3)

我遇到了同样的问题并找到了答案。这是我的问题: What is the use of QThread.wait() function?

要解决您的问题,您不需要在while循环中运行QCoreApplication :: instance() - &gt; processEvents(),您需要做的是,而不是调用quit()尝试向你的创建线程的事件循环发送一个信号(现在被while循环阻止),你必须直接调用它。

因此,对于您的代码,请删除以下行:

connect(this, SIGNAL(finished()), thread, SLOT(quit())); //tried terminate() also

而不是:

emit finished();

使用:

this->thread()->quit();
Tada ......问题解决了。获得的经验:不要尝试通过qt信号槽机制从其中退出工作线程,因为你的信号不会在它们应该的位置结束(你的工作线程的事件循环),但是他们最终在创建线程中。你永远不知道那个线程正在做什么,以及它的事件循环是否正在运行,而且这对你的工作线程来说不应该有用......而是直接调用quit。

答案 2 :(得分:1)

您可以使用Qt :: DirectConnection:

connect(this, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection); 

这会停止线程。

答案 3 :(得分:-1)

而不是执行'doSetup'功能...在moveToThread之前,设置tw的父节点上的SINGALS和tw中的SLOTS之间的连接。

我会做4个连接。 首先是ThreadWorker中的run方法。这简单,自我解释得足够多。

第二个是从完成的信号到下面的第三个SIGNAL连接。退出线程的SIGNAL

第三个应该调用线程的terminate()槽的SIGNAL。当你连接到run方法时,这将有效地关闭事件循环设置(当你执行start()时自动调用exec),并且因为你的run方法不是某种循环,所以会关闭线程而不会出现问题。 / p>

Forth是从线程的terminate()SIGNAL到tw的父级中的SLOT。如果您想在此时执行某些操作,这将显示线程何时死亡。

你做了上面的连接(如果你需要传入字符串,向run方法添加一个变量和相应的SIGNAL连接,你将拥有数据),移动到线程,线程启动,然后执行附加的SIGNAL运行方法。让它做它的事。当它完成时,它将完成一个完成的信号,该信号与另一个与线程终止槽相关联的信号相关联。这将终止事件循环并退出线程,推出已终止的信号,以便您可以执行某些操作。