我应该在线程上调用processEvents()吗?

问题描述 投票:0回答:2

QThread文档提出了两种使代码在单独的线程中运行的方法。如果使用moveToThread方法,则必须调用processEvents()发出超时,才能执行lambda。而且这似乎要花费很多CPU。为什么会这样?

class Worker : public QObject
{
    Q_OBJECT
    QTimer* timer;
    bool m_abort = false;
public:
    Worker() {}
    void abort() {m_abort = true;}

public slots:
    void run() {
        timer = new QTimer;
        connect(timer, &QTimer::timeout, []{qDebug() << "computed";});
        timer->start(1000);
        forever {
            if (m_abort) break;
            QCoreApplication::processEvents();
        }
    }
};

class MainWidget : public QWidget
{
    Q_OBJECT
    QThread thread;
    Worker* worker;
public:
    MainWidget()
    {
        worker = new Worker;
        worker->moveToThread(&thread);
        connect(this, &MainWidget::start, worker, &Worker::run);
        thread.start();
        emit start();
    }
    ~MainWidget(){worker->abort(); thread.quit(); thread.wait();}
signals:
    void start();
};

但是,如果我将QThread子类化并重新实现run(),则不必调用processEvents。而且CPU成本似乎更低。为什么?

class Worker : public QThread
{
public:
    Worker() {}

protected:
    void run() override {
        QTimer timer;
        connect(&timer, &QTimer::timeout, []{qDebug() << "computed";});
        timer.start(1000);
        exec();
    }
};

class MainWidget : public QWidget
{
    Q_OBJECT
    Worker* worker;
public:
    MainWidget()
    {
        worker = new Worker;
        worker->start();
    }
};
c++ multithreading qt qthread qtimer
2个回答
0
投票
但是我仍然不知道为什么我最初的放置方式不起作用。

0
投票
为了让计时器事件调用您的lambda,必须处理事件循环。如果您要像这样修改运行功能:

void run() { timer = new QTimer(this); connect(timer, &QTimer::timeout, []{qDebug() << "computed";}); timer->start(1000); // don't loop here, instead exit the function // and let the thread return back to the event loop }

然后应该调用您的lambda。该线程还将一直运行,直到您调用thread.quit()

注意:您也可以直接连接到线程的'''started'''信号:

connect(&thread, &QThread::started, worker, &Worker::run); thread.start();

© www.soinside.com 2019 - 2024. All rights reserved.