QThread 中的 QTimer 运行

QTimer running in QThread

我需要一个 class 和一个每 100 毫秒执行一次任务的定时器,这个 class 需要 运行 在一个线程中,所以我想结合 qtimer 和 qthread .

我创建了以下代码:

class Worker : public QObject
{
    Q_OBJECT
    public:
    void setEnabled(bool enable);
    
    public slots:
    void initialize();
    
    private:
    void doWork();
    
    QTimer *m_timer;
}

void Worker::initialize()
{
    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &Worker::doWork, Qt::DirectConnection);
    m_timer->start(100);
}

void Worker::setEnabled(bool enable)
{
    if(enable)
        m_timer->start(100);
    else
        m_timer->stop();
}

int main(int argc, char *argv[])
{
    QCoreApplication app(argc,argv);

    QThread *thread = new QThread;
    Worker *worker = new Worker;
    
    QObject::connect(thread, &QThread::started, worker, &Worker::initialize);
    
    worker->moveToThread(thread);
    thread->start();
    
    app.exec();

    delete worker;
    delete thread;
}

通过以下命令,我可以 enable/disable 时间

worker->setEnabled(false); worker->setEnabled(true);

我已经测试过,效果很好,但我想知道这是不是正确的方法?

感谢帮助

不,这并不完全正确。

Worker::setEnabled(bool enable) 也应该是一个插槽,因为它直接调用 QTimer::start() 插槽。直接从主线程调用 Worker::setEnabled 会导致未定义的行为。您必须使用 signal-slot 连接从主线程安全地调用 setEnabled

您还应该在构造函数中初始化 Worker::m_timer 而不是将其推迟到 initialize(),这样如果 Worker::setEnabled 是,您就不会 运行 变成悬空指针调用早于预期。 moveToThread 将用它移动 Worker 的所有子级,所以这是非常理智的行为。

我唯一需要提到的是 m_timer 不能在构造函数中初始化。在这里查看来自 qt 的信息:

顺便说一句,这里要注意的一件极其重要的事情是,您永远不应该在 QObject class 的构造函数中分配堆对象(使用 new),因为随后会执行此分配在主线程上而不是在新的 QThread 实例上,这意味着新创建的对象然后由主线程而不是 QThread 实例拥有。这将使您的代码无法工作。相反,在主函数槽中分配此类资源,例如 initialize() 在这种情况下,当调用该对象时,对象将位于新线程实例上,因此它将拥有资源。