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

在任何地方初始化计时器,但是在线程启动时启动它(将它附加到QThread::started信号):

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

我觉得这种方法有点危险。通过将QObject移动到QThread上,您将使线程负责对象的事件(信号,插槽,消息等)。然而,当对象被删除时,线程将在对象本身之前被删除,这可能导致一些意想不到的行为。

建议的方法是分别实例化线程和对象。

希望对大家有所帮助:

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";
}

最新更新