QT多线程:定时器QTimer和线程QThread常见报错问题

简单的测试demo:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    
    //按钮的创建以及槽函数连接
    m_pStartBut = new QPushButton("start",this);
    m_pStartBut->setGeometry(0,0,100,50);
    m_pEndBut = new QPushButton("END",this);
    m_pEndBut->setGeometry(0,60,100,50);

    connect(m_pStartBut,&QPushButton::clicked,[&]()
    {
        m_pTimer = new QTimer;
        m_pThread = new QThread;
        connect(this, SIGNAL(stop()), m_pTimer, SLOT(stop()),Qt::BlockingQueuedConnection);

        m_pTimer->start(2000); //①部分
        m_pTimer->moveToThread(m_pThread);
        
        //m_pTimer->moveToThread(m_pThread);//错误
        //m_pTimer->start(2000); //错误

        connect(m_pTimer,&QTimer::timeout,[&]()
        {
           qDebug()<<"发送数据";
        });

        m_pThread->start();

    });
    connect(m_pEndBut,&QPushButton::clicked,[&]()
    {
        if(!m_pThread->isFinished())
        {
            
            //m_pTimer->stop(); //错误

            emit stop();//②部分
            if(!m_pTimer->isActive())
            {
                delete m_pTimer;
                m_pTimer = nullptr;
            }
            //退出线程,再删除
            m_pThread->quit();
            m_pThread->wait();
            delete m_pThread;
            m_pThread = nullptr;
            qDebug()<<"exit pthread!";
        }
    });

}


error1:QObject::startTimer: Timers can only be used with threads started with QThread

问题在于demo中的①部分,定时器timer->start(2000)  必须放在timer->moveToThread(pthread)之前,相反则会报以上错误。

error2: QObject::killTimer: Timers cannot be stopped from another thread
                QObject::~QObject: Timers cannot be stopped from another thread


 问题在于demo中的②部分,在次线程中执行主线程对象的一些操作引起的 。

解决方法:如果次线程需要更新主线程对象状态,需要发送消息,主线程对象接收后处理而不能在此线程中直接操作。

 

使用定时器注意事项:

①不能跨线程启动定时器和停止定时器;

②不能跨线程启动一个定时器关联的对象,但在另一个线程释放;

③定时器相关的逻辑和对象只能用在一个线程中。

 

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Qt提供了多种方式来实现多线程,其中不需要重写QThread的方法有以下几种: 1. QtConcurrent:QtConcurrent是Qt提供的一种高级并行编程框架,它支持多线程、并行算法和Lambda表达式。使用QtConcurrent可以方便地实现并行计算,而无需显式地创建线程。例如,使用QtConcurrent::run()函数可以在新线程中执行一个函数,如下所示: ```cpp void myFunction(int parameter) { // do something } QtConcurrent::run(myFunction, parameter); ``` 2. QThreadPool:QThreadPool是Qt提供的一个线程池类,它可以用来管理多个线程。使用QThreadPool可以将任务提交到线程池中,由线程池自动分配线程来执行任务。例如,使用QThreadPool::globalInstance()函数可以获取全局线程池实例,如下所示: ```cpp void myTask(int parameter) { // do something } QThreadPool::globalInstance()->start(new MyTask(parameter)); ``` 3. QTimerQTimerQt提供的一个定时器类,它可以用来定时执行任务。使用QTimer可以在主线程中执行任务,而无需创建新线程。例如,使用QTimer::singleShot()函数可以在一定时间后执行一个函数,如下所示: ```cpp void myFunction() { // do something } QTimer::singleShot(1000, myFunction); ``` 以上三种方法都可以方便地实现多线程,而且不需要显式地创建线程或重写QThread类。但是,需要注意的是,在多线程编程中仍然需要注意线程安全性和避免竞争条件等问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值