解决QTimer报“Timers cannot be started from another thread“错误

    今天在Qt编程时,将QTimer在子线程里执行start()函数,遇到“Timers cannot be started from another thread”问题,使用了如下AI工具,进行查询:
    提示词A:“C++ QTimer 如何跨线程”
    提示词B:“C++ QTimer QThread::run 执行”
    提示词C:“C++ QThread::run 在start()之后 会自动退出吗”

问题原因:QTimer本身不支持跨线程调用
解决方法:QTimer的运行,需要它所在的线程支持事件循环,若没有事件循环,则调用QTimer::start()语句时,会报"Timers cannot be started from another thread"错误,即QTimer失效。
    所以,要想让QTimer在子线程里正常运行,则需要把该子线程的事件循环开启即可。

注意:

  • 若QThread::run()没有被重写override,则默认是开启了事件循环。
  • Qt的主线程,也默认开启了事件循环;
  • C++ std::thread默认没有事件循环;

1 秘塔AI的回答

秘塔AI官网: https://metaso.cn/

1.1 在QThread::run()函数里执行QTimer

    在子线程中创建和使用QTimer:确保QTimer对象在子线程中创建,并且其信号和槽函数也在子线程中处理。
    // 代码: codeA

   void WorkerThread::run()
   {
   
       QTimer timer;
       connect(&timer, &QTimer::timeout, this, &WorkerThread::onTimerTick);
       timer.start(1000); // 每秒触发一次 timeout 信号
       exec(); // 启动事件循环
   }

    codeA的含义是,在QThread::run()里创建一个QTimer对象,然后,也在run()里执行这个QTimer,
并通过exec()启动事件循环。

1.2 将QTimer对象移动到子线程

    创建一个继承自QObject的类,比如Worker类,并在其中创建QTimer对象,然后将该对象移动到子线程中执行。例如:

    // 代码: codeB

   class Worker : public QObject
   {
   
       Q_OBJECT
   private slots:
       void onTimeout()
       {
   
           qDebug() << "Worker::onTimeout get called from?: " << QThread::currentThreadId();
       }
   };

   int main(int argc, char *argv[])
   {
   
       QApplication a(argc, argv);
       qDebug() << "From main thread: " << QThread::currentThreadId();
       QThread t;
       QTimer timer;
       Worker worker;
       QObject::connect(&timer, &QTimer::timeout, &worker, &Worker::onTimeout);
       timer.start(1000);
       worker.moveToThread(&t);
       t.start();
       return a.exec();
   }

1.3 米塔AI的总结

    codeA和codeB,都是把QTimer的执行环境,放到子线程里,

  • 方法A: 通过在QThread::run()里,新建QTimer对象,让QTimer的执行环境处于子线程中,并在子线程里启动事件循环;
  • 方法B: 通过moveThread()函数,把QTimer的执行环境,从主线程移动到子线程;
    然后,再调用QTimer::start()函数,即可运行定时器,从而解决"Timers cannot be started from another thread"问题

2 DeepSeek的回答

    DeepSeek官网: https://chat.deepseek.com/
    其他版本的DeepSeek,比如超算中心DeepSeek网站: https://chat.scnet.cn/#/home

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sanqima

一键三连,多多益善

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值