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

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

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

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


void Widget::on_pushButton_clicked()
{
    qDebug()<<"主线程ID:"<<QThread::currentThreadId();
    myThread->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:"<<QThread::currentThreadId();
    timer->start(1000);
}
 
void MyThread::timerOut()
{
    qDebug()<<"当前线程ID:"<<QThread::currentThreadId();
}

输出线程:
请添加图片描述
错误原因: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:"<<QThread::currentThreadId();

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

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

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


void MyThread::run()
{
    timer = new QTimer();
    connect(timer,SIGNAL(timeout()),this,SLOT(timerOut()),Qt::DirectConnection);
    startTimer();
    exec();
}
 
void MyThread::startTimer(){
    qDebug()<<"当前线程ID:"<<QThread::currentThreadId();
    timer->start(1000);
}
 
void MyThread::timerOut()
{
    qDebug()<<"当前线程ID:"<<QThread::currentThreadId();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值