[英]QTimer doesn't call timeout slot
我试图在不同的QThread
使用QTimer
,但无法连接到QTimer
的timeout()
插槽。
我究竟做错了什么?
这是我的代码:
extern MainWindow *mainClass;
class myObj : public QObject
{
Q_OBJECT
public:
explicit myObj(QObject *parent = 0);
~myObj();
QThread workerThread;
int percent;
QTimer *percentTimer;
public slots:
void doWork();
void percentUpdate();
void startFunction();
signals:
void start();
void UpdateResult();
};
myObj::myObj(QObject *parent) : QObject(parent)
{
moveToThread(&workerThread);
connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater()));
connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult()));
connect(&workerThread, SIGNAL(started()), this, SLOT(doWork()));
connect(this, SIGNAL(start()), this, SLOT(startFunction()));
percent++;
percentTimer = new QTimer();
percentTimer->moveToThread(&workerThread);
percentTimer->setInterval(1000);
connect(percentTimer, SIGNAL(timeout()), this,SLOT(percentUpdate()));
}
myObj::~myObj() {
workerThread.quit();
workerThread.wait();
if (percentTimer) percentTimer->deleteLater();
}
void myObj::doWork()
{
emit start();
workerThread.exec();
}
void myObj::startFunction()
{
percentTimer->start();
QThread::sleep(60);
percentTimer->stop();
}
void myObj::percentUpdate()
{
qDebug() << "In Timer" << percent++;
emit UpdateResult();
}
这是因为您试图从与创建它的线程不同的线程中启动QTimer。 使用QTimer和线程时,应该非常小心在将控制它的线程中创建QTimer。
从QTimer类文档 :
在多线程应用程序中,可以在具有事件循环的任何线程中使用QTimer。 要从非GUI线程启动事件循环,请使用QThread :: exec()。 Qt使用计时器的线程关联性来确定哪个线程将发出timeout()信号。 因此, 您必须在其线程中启动和停止计时器 。 无法从另一个线程启动计时器。
在您的情况下, percentTimer = new QTimer();
从主线程执行(即使您之前使用过moveToThread
,但仍是执行它的主线程),而doWork
和start
信号是从workerThread
发出的。
例如,您可以从workerThread
调用的void init()
插槽中而不是在构造函数中执行new QTimer
,以确保QTimer
由适当的线程创建和拥有。
myObj::myObj(QObject *parent) : QObject(parent), percentTimer(nullptr)
{
moveToThread(&workerThread);
connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater()));
connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult()));
connect(&workerThread, SIGNAL(started()), this, SLOT(init()));
connect(&workerThread, SIGNAL(started()), this, SLOT(doWork()));
connect(this, SIGNAL(start()), this, SLOT(startFunction()));
percent++;
}
void myObj::init() {
percentTimer = new QTimer();
percentTimer->setInterval(1000);
connect(percentTimer, SIGNAL(timeout()), this, SLOT(percentUpdate()));
}
首先,您应该使用workerThread
来让myObj
在其上下文中工作( 在创建所需的连接后启动它,因为连接到start
信号的插槽可能不会执行)。 而不是使用QThread::sleepFor
您应该使用这样的东西:
QEventLoop loop;
QTimer::singleShot(60000, &loop, SLOT(exit()));
loop.exec();
创建延迟,因为QThread::sleepFor
冻结了整个线程的执行。 因此,绑定到该线程的事件都不会被处理。
这里的workerThread.exec()
是没有用的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.