【问题标题】:How to properly stop QTimer from another thread如何从另一个线程正确停止 QTimer
【发布时间】:2020-06-24 05:46:32
【问题描述】:

我看到这样的话题被讨论了很多次,但是对于简单的情况找不到明确的答案。我有 Worker 类在我创建计时器的自己的线程中运行,并且由于某些情况想要停止它。 但我得到了错误:

定时器不能从另一个线程停止

我补充说在 Qt 中工作的线程中缺少一些核心逻辑。有人可以解释如何解决这个问题吗?谢谢。

这里是main.cpp

#include <QCoreApplication>
#include <QObject>
#include <QtDebug>

#include "worker.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Worker w;

    return a.exec();
}

工人.h

#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include <QTimer>
#include <QThread>
#include <QtDebug>

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);
private:
    QThread t;
    QTimer *timer;

    int count = 1;

public slots:

    void dataTimerFunction();
    void onStopTimer(QTimer *t);
signals:
    void stopTimer(QTimer *t);
};

#endif // WORKER_H

工人.cpp

#include "worker.h"

Worker::Worker(QObject *parent) : QObject(parent)
{
    this->moveToThread(&t);
    QObject::connect(&t, &QThread::finished, this, &QObject::deleteLater);

    t.start();

    // are we in the new thread from this point, right?
    timer = new QTimer();
    QObject::connect(timer, &QTimer::timeout, this, &Worker::dataTimerFunction);
    QObject::connect(this, &Worker::stopTimer, this, &Worker::onStopTimer);
    // QObject::connect(this, &Worker::stopTimer, this, &Worker::onStopTimer, Qt::QueuedConnection);  doesn't work as well
    timer->start(200);
}

void Worker::dataTimerFunction()
{
    qDebug()<<count;
    count++;
    if (count>5){
        emit stopTimer(timer);
        //timer->stop();
    }
}

void Worker::onStopTimer(QTimer *t)
{
    t->stop();
}

【问题讨论】:

  • timer 是否与Worker 在同一个线程中?我想,没有。
  • 我认为是。我正在将 Worker 移动到线程并在初始化计时器之前运行它
  • 这还不够。 QObject 的成员变量不会自动成为它的子变量,因此保留在旧线程中。为了证明这一点,只需比较您的 Worker 对象和计时器的线程指针。
  • 好主意,我会试试看

标签: qt qthread qtimer


【解决方案1】:

问题确实是计时器没有移动到你的线程。

这是一个修改后的工人类,它可以实现您可能想要实现的目标。它也将计时器移动到线程,然后使用信号/插槽启动和停止它。

worker.h

#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include <QTimer>
#include <QThread>
#include <QtDebug>

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);
private:
    QThread t;
    QTimer *timer;

    int count = 1;

signals:
    void stopTimer();
    void startTimer(int msec);

public slots:

    void dataTimerFunction();
};

#endif // WORKER_H

worker.cpp

#include "worker.h"

Worker::Worker(QObject *parent) : QObject(parent)
{
    // are we in the new thread from this point, right?
    timer = new QTimer(nullptr);

    this->moveToThread(&t);
    timer->moveToThread(&t);
    QObject::connect(&t, &QThread::finished, this, &QObject::deleteLater);
    t.start();

    QObject::connect(timer, &QTimer::timeout, this, &Worker::dataTimerFunction);
    QObject::connect(this, &Worker::stopTimer, timer, &QTimer::stop, Qt::QueuedConnection);  
    QObject::connect(this, &Worker::startTimer, timer, static_cast<void (QTimer::*)(int)>(&QTimer::start), Qt::QueuedConnection);  
    startTimer(200);
}



void Worker::dataTimerFunction()
{
    qDebug()<<count;
    count++;
    if (count>5){
        stopTimer();
    }
}

【讨论】:

  • 哦,我明白了,我今天就试试这个。调用 moveToThread 后,从什么时候开始从这个新线程评估类方法?在 thread.start() 之后?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多