QTimer特点
- 不能跨线程启动和停止定时器。
- 不能在一个线程中启动定时器关联的对象,而在另一个线程释放(析构)此定时器关联的对象。
- 原因:定时器相关的逻辑和数据结构与线程关联,只能在同一个线程中。
- Timer的任务超时,会把定时阻塞。
解决方案1-标准方式
TestTimer2::TestTimer2(QObject *parent)
{//使用指针变量m_thread = new QThread(this);m_timer = new QTimer(0);m_timer->setInterval(1000);m_timer->moveToThread(m_thread);//定时任务放在线程中执行,必须指定参数-Qt::DirectConnectionconnect(m_timer, &QTimer::timeout, this, &TestTimer2::updateTimer, Qt::DirectConnection);void (QTimer::*pStartFun)() = &QTimer::start;connect(m_thread, &QThread::started, m_timer, pStartFun);connect(m_thread, &QThread::finished, m_timer, &QTimer::stop);//启动m_thread->start();
}TestTimer2::~TestTimer2()
{//销毁指针变量-注意先后顺序if(m_thread){qInfo()<<"delete thread";m_thread->quit();m_thread->wait();delete m_thread;m_thread = nullptr;}if(m_timer){qInfo()<<"delete timer";delete m_timer;m_timer = nullptr;}
}
解决方案2-简化版本
TestTimer2::TestTimer2(QObject *parent)
{//使用指针变量m_thread = new QThread(this);m_timer = new QTimer(0);m_timer->setInterval(1000);//定时任务放在线程中执行,必须指定参数-Qt::DirectConnectionconnect(m_timer, &QTimer::timeout, this, &TestTimer2::updateTimer, Qt::DirectConnection);connect(m_thread, &QThread::finished, m_timer, &QTimer::stop);//启动m_thread->start();//简化点: 先启动定时器,后移动线程m_timer->start();m_timer->moveToThread(m_thread);
}TestTimer2::~TestTimer2()
{//销毁指针变量-注意先后顺序if(m_thread){qInfo()<<"delete thread";m_thread->quit();m_thread->wait();delete m_thread;m_thread = nullptr;}if(m_timer){qInfo()<<"delete timer";delete m_timer;m_timer = nullptr;}
}
解决方案3-使用普通变量
TestTimer2::TestTimer2(QObject *parent)
{//使用普通变量m_timer.setInterval(1000);//定时任务放在线程中执行,必须指定参数-Qt::DirectConnectionconnect(&m_timer, &QTimer::timeout, this, &TestTimer2::updateTimer, Qt::DirectConnection);connect(&m_thread, &QThread::finished, &m_timer, &QTimer::stop);//启动m_thread.start();//简化点: 先启动定时器,后移动线程m_timer.start();m_timer.moveToThread(&m_thread);
}TestTimer2::~TestTimer2()
{m_thread.quit();m_thread.wait();
}
最后:这样就可以实现定时器在单独的线程中执行,且不会出现跨线程异常。