美文网首页
QTimer在QThread中失效

QTimer在QThread中失效

作者: NullUser | 来源:发表于2021-08-01 23:25 被阅读0次

通过继承QThread类重写run函数实现多线程时,在run()中开启QTimer,并连接timeout信号,会发现无法收到timeout信号,从而导致无法执行槽函数。
根据QT对QTimer的官方介绍:
In multithreaded applications, you can use “QTimer” in any thread that has an event loop. To start an event loop from a non-GUI thread, use “QThread::exec()”. Qt uses the timer's “thread affinity” to determine which thread will emit the “timeout()” signal. Because of this, you must start and stop the timer in its thread; it is not possible to start a timer from another thread.
QTimer是基于事件循环的,如果自定义线程中没有开启事件循环,那么QTimer相应的也不会起作用。QThread提供了exec()函数,可以开启事件循环,从而可以正常使用QTimer。

测试demo如下:
MyTimer类
mytimer.h

#ifndef MYTIMER_H
#define MYTIMER_H
#include <QObject>
#include <QMutex>

class QTimer;
class MyTimer:public QObject
{
    Q_OBJECT
public:
    static MyTimer* getInstance();

private:
    MyTimer();

private slots:
    void slotTest();

private:
    QTimer *m_timer;
    static MyTimer *ins;
    static QMutex mute;
};

#endif // MYTIMER_H

mytimer.cpp

#include "mytimer.h"
#include <QTimer>
#include <QDebug>

MyTimer *MyTimer::ins = nullptr;
QMutex MyTimer::mute;

MyTimer::MyTimer():
    m_timer(new QTimer(this))
{
    connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTest()));
    m_timer->start(1000);
}

MyTimer* MyTimer::getInstance()
{
    if(ins == nullptr)
    {
        mute.lock();
        if(ins == nullptr)
        {
            ins = new MyTimer();
        }
        mute.unlock();
    }

    return ins;
}

void MyTimer::slotTest()
{
    qDebug()<<"test";

}

MyThread类

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include "mytimer.h"

class MyThread : public QThread
{
public:
    MyThread();
    void run() override
    {

        MyTimer::getInstance();
        //开启事件循环  
        exec();
    }
};

#endif // MYTHREAD_H

MyTimer使用单例模式,在构造对象时,实例化QTimer,并通过QTimer每秒打印一个test。如果我们首先在MyThread线程中调用MyTimer::getInstance(),那么该单例对象在MyThread中构造,从而QTimer是在MyThread中创建的,如果在run()函数中没有执行exec(),那么就没有开启事件循环,导致QTimer的定时任务不起作用。当我们在run()中执行exec()后,该线程拥有event loop,便可确保QTimer正常工作。

相关文章

网友评论

      本文标题:QTimer在QThread中失效

      本文链接:https://www.haomeiwen.com/subject/mjxdvltx.html