QObject::startTimer: таймеры могут использоваться только с потоками, запущенными с QThread
Я пытаюсь запустить таймер в цикле событий рабочего потока, но я получаю эту ошибку:QObject::startTimer: Timers can only be used with threads started with QThread
Что не так с этим?
#include <QObject>
#include <QThread>
#include <QTimer>
class A : public QObject
{
Q_OBJECT
public:
A();
private:
QThread m_workerThread;
QTimer m_myTimer;
};
A::A()
{
this->moveToThread(&m_workerThread);
m_myTimer.moveToThread(&m_workerThread);
m_workerThread.start();
m_myTimer.start(1000);
}
3 ответа
Инициализируйте свой таймер в любом месте, но запустите его прямо при запуске потока (присоедините его к сигналу QThread::start):
class A : public QObject
{
Q_OBJECT
public:
A();
private slots:
void started();
void timeout();
private:
QThread m_workerThread;
QTimer m_myTimer;
};
A::A()
{
moveToThread(&m_workerThread);
connect(&m_workerThread, SIGNAL(started()), this, SLOT(started()));
connect(&m_myTimer, SIGNAL(timeout()), this, SLOT(timeout()));
m_myTimer.setInterval(1000);
m_myTimer.moveToThread(&m_workerThread);
m_workerThread.start();
}
void A::started()
{
timer.start();
}
void A::timeout()
{
// timer handler
}
Я думаю, что я понял это, я попытался запустить таймер из потока GUI, после того, как я переместил его в рабочий поток, вот как это работает:
class A : public QObject
{
Q_OBJECT
public:
A();
private:
QThread m_workerThread;
QTimer m_myTimer;
public slots:
void sl_startTimer();
};
A::A()
{
this->moveToThread(&m_workerThread);
m_myTimer.moveToThread(&m_workerThread);
m_workerThread.start();
QMetaObject::invokeMethod(this, "sl_startTimer", Qt::QueuedConnection);
}
void A::sl_startTimer()
{
m_myTimer.start(1000);
}
Надеюсь, это будет полезно:
class ReadYoloResult : public QObject
{
Q_OBJECT
public:
ReadYoloResult(QObject *parent = 0);
void startTimer();
QThread workerThread;
private:
QTimer *timer;
public slots:
void timerSlot();
};
ReadYoloResult::ReadYoloResult(QObject * parent)
{
this->moveToThread(&workerThread);
timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(timerSlot()));
workerThread.start();
//timer->start(1000);
}
void ReadYoloResult::startTimer(){
timer->start(100);
}
void ReadYoloResult::timerSlot(){
qDebug()<<"In timer slot";
}
Этот подход кажется мне немного опасным. Перемещая QObject
на QThread
вы делаете поток ответственным за события объекта (сигналы, слоты, сообщения и т. д.). Однако при удалении объекта поток будет удален раньше самого объекта, что может привести к непредвиденным последствиям.
Рекомендуемый подход состоит в том, чтобы создать экземпляр потока и объекта отдельно.