QTimer的跨线程启动问题

本文探讨了如何在Qt中避免在工作线程上启动QTimer引发的错误,通过将`startTimer`函数改为槽函数并使用`invokeMethod`确保线程同步。问题与解决方案有助于理解多线程环境下计时器的正确使用。

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

记录一个跨线程启动QTimer的问题。问题是个小问题,但是不注意的话就不是知道为啥咱的计时器它咋就坏了呢。

先看个示例代码:(为简洁 部分省略[手动狗头])

//*.h

//主窗口类
class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

    void startTimer();

public slots:
    void slotTimeout();

private:
    Ui::Dialog *ui;
    QTimer timer;
};

//工作线程
class WorkThread : public QThread
{
    Q_OBJECT
public:
    WorkThread(QObject* parent);
protected:
    virtual void run() override;
};


///
//*.cpp

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    qDebug() << "Main:" << QThread::currentThreadId();

    timer.setSingleShot(true);
    connect(&timer, &QTimer::timeout,this, &Dialog::slotTimeout);

    startTimer();

    WorkThread* th = new WorkThread(this);
    th->start();
}

void Dialog::startTimer()
{
    qDebug() << __FUNCTION__ << QThread::currentThreadId();
    timer.start(1000);
}

void Dialog::slotTimeout()
{
    qDebug() << __FUNCTION__;
}

WorkThread::WorkThread(QObject *parent):QThread(parent)
{}

void WorkThread::run()
{
    qDebug() << "Thread id:" << QThread::currentThreadId();
    QThread::sleep(3);
    qobject_cast<Dialog*>(parent())->startTimer();

    QThread::exec();
}

这一小段干了什么呢?计时器设置成单发,主窗口类Dialog启动了一次计时器;接着启动了一个线程,线程也启动了一次计时器,只不过让线程休息3秒后才启动。看结果:

 从结果上看,线程启动的QTimer似乎失败了 Qt直接给了错误消息,告诉我们不能从另一个线程中启动计时器。赶紧看看文档

 上面巴拉巴拉的就不看了,直接看重点,我们必须要在他所在线程中启动停止。人家都说这么明白了,改吧。

//第一 startTimer改成槽函数
public slots:
    void startTimer(); 
    void slotTimeout();

//第二 调用用invokeMethod
//qobject_cast<Dialog*>(parent())->startTimer();
QMetaObject::invokeMethod(parent(),"startTimer",Qt::QueuedConnection);

用invokeMethod就省去了再定义信号,关联信息这两步,非常方便。

再看结果,没毛病了。从线程中调用的startTimer 线程id也成了主线程id。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JL_MG

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值