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

标签 c++ multithreading qt qthread qtimer

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

最佳答案

您的 run() 函数“阻塞”了线程。它在线程上下文中被调用,但从不返回。这意味着,一旦调用 run() 函数,线程中的事件循环就不再执行。

为了调用您的 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();

关于c++ - 我应该在线程上调用 processEvents() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59631918/

相关文章:

c++ - 类的部分模板特化

c++ - C++:如何使用正则表达式从字符串中提取单词

关于 linux 内存问题的 C++ 多线程程序

c++ - linux qt中的gsoap undefined reference

c++ - boost 程序选项 parse_config_file

c++ - 我可以遍历仅相差一个整数的文件名吗?

c++ - 通过它自己的条件变量c++控制每个线程

java - 如何在多线程程序中保存线程变量的值

.net - Threading.Tasks Dispose 含义问题

c++ - QAudioDeviceInfo 在 Ubuntu 上找不到默认音频设备