[英]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.