我试图在一个单独的线程中执行一些工作,并在工作完成时停止该线程。
我已经设置了这样的连接
thread.connect( workerClass, SIGNAL( finished() ), SLOT( quit() ) );
但是当我发出finished()信号时,从不调用quit()槽。命令行不显示与失败连接相关的任何警告。
我创建了一个简单的测试项目来缩小问题范围并得到相同的行为:
TestClass.h:
#ifndef TESTCLASS_H
#define TESTCLASS_H
class TestClass : public QObject
{
Q_OBJECT
public:
TestClass() { }
signals:
void finished();
public slots:
void doWork();
}
#endif // TESTCLASS_H
TestClass.cpp:
#include "TestClass.h"
#include <QtCore/QDebug>
void TestClass::doWork()
{
qDebug() << "Starting";
for( long i = 0; i < 1000000000; i++ );
qDebug() << "Done";
emit finished();
};
和main.cpp:
#include <QtCore/QCoreApplication>
#include <QtCore/QThread>
#include "TestClass.h"
int main( int argc, char* argv[] )
{
QCoreApplication a( argc, argv );
TestClass testClass;
QThread testThread;
testClass.moveToThread( &testThread );
testThread.connect( &testClass, SIGNAL( finished() ), SLOT( quit() ) );
testClass.connect( &testThread, SIGNAL( started() ), SLOT( doWork() ) );
testThread.start();
testThread.wait();
return 0;
}
所以这就是我期望发生的事情:
testThread.start()
,就会调用线程的run()
函数,该函数在内部调用exec()
并启动事件循环。此外,它会抛出started()
信号。testClass
名为doWork()
广告位。TestClass::doWork()
后,会抛出finished()
信号。testThread
的事件循环接收信号并将其转发至quit()
广告位testThread.wait()
在线程结束时从等待返回。步骤1-3工作,我得到qDebug()
输出。
问题出在第4步:信号被触发并转发到某个事件循环(我调试了一下,但无法确定它被触发了哪个事件循环),但永远不会调用quit()
插槽。
我做错了什么?
P.S。:请不要建议继承QThread,我尝试这种方式的全部意义是因为我想避免继承QThread。
答案 0 :(得分:5)
我认为问题是你实际上没有在场景中运行Qt事件循环。如果将testThread.wait()
替换为a.exec()
(启动Qt事件循环),您应该会看到您的信号/插槽得到正确处理。
如果您希望应用程序在线程完成后退出,您可以使用QCoreApplication的quit()
插槽来执行此操作。
答案 1 :(得分:1)
我遇到了同样的问题并找到了答案。这是我的问题: What is the use of QThread.wait() function?
要解决您的问题,您不需要运行a.exec(),您需要做的是,而不是调用尝试向您的应用程序的事件循环发送信号的quit()(显然不存在),你必须直接调用它。
因此,对于您的代码,请删除以下行:
testThread.connect( &testClass, SIGNAL( finished() ), SLOT( quit() ) );
而不是:
emit finished();
使用:
this->thread()->quit();
Tada ......问题解决了。获得的经验:不要试图通过qt信号槽机制退出工作线程,因为你的信号不会在它们应该的位置结束(你的工作线程的事件循环),但它们最终会在创建中而是线程。你永远不知道那个线程正在做什么,以及它的事件循环是否正在运行,这对你的工作线程来说应该是不可行的......相反,直接调用quit。