[英]QTimer doesn't call timeout slot
I was trying to use a QTimer
within different QThread
, but I couldn't connect to the QTimer
's timeout()
slot. 我试图在不同的QThread
使用QTimer
,但无法连接到QTimer
的timeout()
插槽。
What am I doing wrong? 我究竟做错了什么?
Here is my code: 这是我的代码:
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();
}
This is because you are trying to start your QTimer from a different thread than the one that created it. 这是因为您试图从与创建它的线程不同的线程中启动QTimer。 When using QTimer and threads, you should be very careful to create your QTimer in the thread that will control it. 使用QTimer和线程时,应该非常小心在将控制它的线程中创建QTimer。
From QTimer class documentation : 从QTimer类文档 :
In multithreaded applications, you can use QTimer in any thread that has an event loop. 在多线程应用程序中,可以在具有事件循环的任何线程中使用QTimer。 To start an event loop from a non-GUI thread, use QThread::exec(). 要从非GUI线程启动事件循环,请使用QThread :: exec()。 Qt uses the timer's thread affinity to determine which thread will emit the timeout() signal. Qt使用计时器的线程关联性来确定哪个线程将发出timeout()信号。 Because of this, you must start and stop the timer in its thread ; 因此, 您必须在其线程中启动和停止计时器 。 it is not possible to start a timer from another thread. 无法从另一个线程启动计时器。
In your case percentTimer = new QTimer();
在您的情况下, percentTimer = new QTimer();
is executed from the main thread, (even though you used moveToThread
before, this is still the main thread executing it), while your doWork
and start
signals are emitted from workerThread
. 从主线程执行(即使您之前使用过moveToThread
,但仍是执行它的主线程),而doWork
和start
信号是从workerThread
发出的。
You can for instance do your new QTimer
from a void init()
slot called from your workerThread
, rather than in the constructor, to ensure that the QTimer
is created and owned by the proper thread. 例如,您可以从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()));
}
First of all, you should shart workerThread
to let myObj
work in its context (start it after creating required connections because slots connected to start
signal possibly would not be executed otherwise). 首先,您应该使用workerThread
来让myObj
在其上下文中工作( 在创建所需的连接后启动它,因为连接到start
信号的插槽可能不会执行)。 Instead of using QThread::sleepFor
you should use something like this: 而不是使用QThread::sleepFor
您应该使用这样的东西:
QEventLoop loop;
QTimer::singleShot(60000, &loop, SLOT(exit()));
loop.exec();
to create delays, because QThread::sleepFor
freezes overall thread execution. 创建延迟,因为QThread::sleepFor
冻结了整个线程的执行。 And so none of your events will be processed that bound to this thread. 因此,绑定到该线程的事件都不会被处理。
workerThread.exec()
is useless here. 这里的workerThread.exec()
是没有用的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.