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

QThread - Using a slot quit() to exit the thread

本文关键字:退出 线程 quit 使用 slot QThread      更新时间:2023-10-16

我想在线程完成运行时通知对象。但是,我无法使线程正确退出。我有以下代码:

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)

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

尝试删除while循环,添加一个插槽workDone()(或任何你想叫它)到Processor.cpp,并连接到你的Threadworkerfinished()信号。

我有同样的问题,并找到了答案。我的问题是:QThread.wait()函数的用途是什么?

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

所以在你的代码中,删除这行:

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

而不是:

emit finished();

使用:

this->thread()->quit();

漏掉什么问题解决了。经验教训:不要试图通过qt信号槽机制从工作线程中退出,因为你的信号不会在它们应该在的地方结束(你的工作线程的事件循环),而是在创建线程中结束。你永远不知道那个线程在做什么,也不知道它的事件循环是否正在运行,这对你的工作线程来说应该无关紧要……请直接调用quit。

您可以使用Qt::DirectConnection:

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

而不是做你的'doSetup'函数…在moveToThread之前,在tw的父节点上的SINGALS和tw中的SLOTS之间建立连接。

我将做4个连接。首先是ThreadWorker中的run方法。这很简单,不言自明。

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

第三个应该调用线程的terminate()槽的SIGNAL。这将在连接到run方法时有效地关闭事件循环设置(执行start()时会自动调用exec),并且由于您的run方法不是某种类型的循环,因此将毫无问题地关闭线程。

Forth是从线程终止的()SIGNAL到父线程的SLOT。如果你想在线程死亡的时候做点什么,这将告诉你。

你做上面的连接(如果你需要传递字符串,添加一个变量到run方法和相应的SIGNAL连接,你就会有数据),移动到线程,线程启动,然后做附加到run方法的SIGNAL。随它去吧。当它完成时,它将执行一个已完成的信号,该信号绑定到另一个绑定到线程终止槽的信号。这将终止事件循环并退出线程,将终止的信号推出,以便您可以执行操作。