Как правильно остановить QTimer из другого потока - PullRequest
0 голосов
/ 12 марта 2020

Я вижу, что такие темы c обсуждались много раз, но не могу найти четкого ответа на простую ситуацию. У меня есть класс Worker, работающий в собственном потоке, где я создаю таймер и хочу остановить его из-за какого-либо условия. Но я получаю сообщение об ошибке:

Таймеры не могут быть остановлены из другого потока

Я заполняю, что отсутствуют некоторые основные логики c в потоке, работающем в Qt. Может кто-нибудь объяснить, пожалуйста, как решить эту проблему? Спасибо.

Вот главное. 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();
}

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;

public slots:

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

#endif // WORKER_H

Worker. 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();
}

1 Ответ

0 голосов
/ 12 марта 2020

Проблема действительно в том, что таймер не перемещен в ваш поток.

Вот модифицированный рабочий класс, который делает то, чего вы, возможно, захотите достичь. Он перемещает таймер также в поток, а затем запускает и останавливает его, используя сигналы / слоты.

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();
    }
}
...