Qt多线程中使用QTimer(常见问题汇总)

我们经常需要将一些耗时的工作在子线程中进行,同时在子线程中又需要用到循环事件时,一种方法使用While()/sleep()进行线程控制。另一种创建一个QTimer对象,使用信号与槽机制将信号timeout()与相应的槽函数相连,然后调用start()函数。接下来,每隔一段时间,定时器便会发出一次timeout()信号,此种方法使用更为灵活,方便,注意:启用计时器时需启动事件循环exec()

下面我使用一个DEMO进行展示:

自定义一个Button,当点击按钮时,线程启动,输出当前运行的线程ID:

void Widget::on_pushButton_clicked()
{
    qDebug()<<"主线程ID:"<start();
}

 

常见错误1:在线程构造函数中初始化QTimer:

MyThread::MyThread(QObject *parent):QThread (parent)
{
    timer = new QTimer();
}

错误原因:线程类的初始化在主线程中,因此线程构造函数也在主线程中运行

常见错误2:在线程中为QTimer指定父类:

void MyThread::run()
{
    timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()));
    timer->start(1000);
    exec();
}

错误原因同上

常见错误3:计时器虽在线程中初始化,但在子线程非run()函数中开始start()。

void MyThread::run()
{
    timer = new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()));
    startTimer();
    exec();
}
 
void MyThread::startTimer(){
    qDebug()<<"当前线程ID:"<start(1000);
}
 
void MyThread::timerOut()
{
    qDebug()<<"当前线程ID:"<

输出线程:

Qt多线程中使用QTimer(常见问题汇总)_第1张图片

错误原因:run()函数线程为子线程,因此run函数中运行startTimer()为run所处线程,但因为startTimer()初始化时为主线程,因此timer->start()也随之在主线程中开始,计时器槽函数也在主线程中运行

正确用法1:

void MyThread::run()
{
    timer = new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()));
    timer->start(1000);
    exec();
}
 
void MyThread::timerOut()
{
    qDebug()<<"当前线程ID:"<

打印线程:

 Qt多线程中使用QTimer(常见问题汇总)_第2张图片

正确用法2:

如果我不想在run()函数中就开始计时器,而是在线程运行过程中根据实际情况开启(之前错误3的情况)时要怎么办呢?

解决办法为:信号与槽连接中使用Qt::DirectConnection

信号与槽连接默认方式为:Qt::AutoConnection,因此会根据函数所处的线程自动跳转,导致错误3中的情况

oid MyThread::run()
{
    timer = new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()),Qt::DirectConnection);
    startTimer();
    exec();
}
 
void MyThread::startTimer(){
    qDebug()<<"当前线程ID:"<start(1000);
}
 
void MyThread::timerOut()
{
    qDebug()<<"当前线程ID:"<

 打印线程:

Qt多线程中使用QTimer(常见问题汇总)_第3张图片

 

 

你可能感兴趣的:(Qt)