QObject::killTimer: timers cannot be stopped from another thread-解决方案

本文详细介绍了QTimer在Qt中的使用限制,强调了不能跨线程启动和停止定时器,以及可能导致的问题。提供了三种解决方案,包括标准方式、简化版本和使用普通变量的方法,确保定时器在单独线程中安全执行。在析构时,遵循特定的销毁顺序,以避免异常。这些方案有助于避免线程安全问题,确保程序稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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::DirectConnection
    connect(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::DirectConnection
    connect(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::DirectConnection
    connect(&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();
}

最后:这样就可以实现定时器在单独的线程中执行,且不会出现跨线程异常。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值