簡體   English   中英

QTimer不調用超時槽

[英]QTimer doesn't call timeout slot

我試圖在不同的QThread使用QTimer ,但無法連接到QTimertimeout()插槽。

我究竟做錯了什么?

這是我的代碼:

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 ,但仍是執行它的主線程),而doWorkstart信號是從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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM