QThread在c++中的基本使用

Posted

技术标签:

【中文标题】QThread在c++中的基本使用【英文标题】:QThread Basic use in c++ 【发布时间】:2016-11-29 11:53:07 【问题描述】:

我有一个包含 GUI 的 c++ 代码,我需要在其中运行一个耗时的循环进行优化。

class OptimizationAlgorith(data *data);

private:
    var var1;
    var var2;
public:
    method1();
    method2();
    ..
    timeConsumingMethod(data);

这需要在 GUI 类中调用,如下所示:

    class QRegistration: public QWidget

    Q_OBJECT
private:
    data *m_data;
    QPushButton     *m_button_run;
    OptimizationAlgorithm *m_optimizationalgorithm;
    WorkerThread *m_workerThread;
    QThread *m_thread;
    ..
private slots:
    void on_pushButton_run_clicked();
    void registrationDone();

我需要将timeConsumingMethod 移动到与主线程不同的线程中,以便在timeConsumingMethod 运行时GUI 不会冻结。 我使用 Qt 的官方文档创建了一个新类“WorkerThread”,如下所示:

class WorkerThread : public QObject

    Q_OBJECT

public:
    WorkerThread(ApplicationData* data, QOptimizationAlgorithm * OptimizationAlgorithm);
    ~WorkerThread();

    public slots:
        void run(data* data);

signals:
    void finished();
    private slots:

private:
    OptimizationAlgorithm *m_OptimizationAlgorithm;
    ApplicationData *m_data;

我现在应该如何在WorkerThread 中实现我的run()?我可以简单地写吗:

void WorkerThread::run(data *m_data)

    m_optimization.timeConsumingMethod(m_data);
    emit finished();

还是我必须将timeConsumingMethod 的整个定义复制到run() 中?为什么/为什么不?

【问题讨论】:

如果您使用“worker”模式,则无需重新实现run 方法。尝试阅读Qt文档,有完美的例子。 你不必复制timeConsumingMethod的整个定义,在run()中调用的任何代码都会在WorkerThread的线程中执行,以证明使用QThread::currentThreadId()函数来获取线程id。 【参考方案1】:

您不需要进行任何显式的线程管理,Qt 已经为您完成了。使用QtConcurrent::run 在线程池中的工作线程中完成工作。

您还应该将管理工作的控制器与 UI 分离。如何耦合这些对象的知识应该与对象本身分开。这使得 UI 和控制器的设计更加灵活,并有助于避免因从不正确的线程访问非线程安全方法而导致的几类错误。

完整示例:

// https://github.com/KubaO/***n/tree/master/questions/threadwork-simple-40865259
#include <QtWidgets>
#include <QtConcurrent>

struct ApplicationData ;

struct OptimizationAlgorithm 
   void timeConsumingMethod(QSharedPointer<ApplicationData>) 
      QThread::sleep(3);
   
;

class Controller : public QObject 
   Q_OBJECT
   QSharedPointer<ApplicationData> m_datanew ApplicationData;
   OptimizationAlgorithm m_algorithm;
public:
   Q_SLOT void run() 
      QtConcurrent::run([this]
         emit busy();
         m_algorithm.timeConsumingMethod(m_data);
         emit finished();
      );
   
   Q_SIGNAL void busy();
   Q_SIGNAL void finished();
;

class Registration : public QWidget 
   Q_OBJECT
   QVBoxLayout m_layoutthis;
   QLabel m_status"Idle";
   QPushButton m_run"Run";
public:
   Registration() 
      m_layout.addWidget(&m_status);
      m_layout.addWidget(&m_run);
      connect(&m_run, &QPushButton::clicked, this, &Registration::reqRun);
   
   Q_SIGNAL void reqRun();
   Q_SLOT void onBusy()  m_status.setText("Running"); 
   Q_SLOT void onFinished()  m_status.setText("Idle"); 
;

void setup(Registration *reg, Controller *ctl) 
   using Q = QObject;
   Q::connect(reg, &Registration::reqRun, ctl, &Controller::run);
   Q::connect(ctl, &Controller::busy, reg, &Registration::onBusy);
   Q::connect(ctl, &Controller::finished, reg, &Registration::onFinished);


int main(int argc, char ** argv) 
   QApplication appargc, argv;
   Controller ctl;
   Registration reg;
   setup(&reg, &ctl);
   reg.show();
   return app.exec();

#include "main.moc"

【讨论】:

以上是关于QThread在c++中的基本使用的主要内容,如果未能解决你的问题,请参考以下文章

是否可以从 QThread 内部使用 opencv 函数?

C++ 中的基本 GUI 功能

PyQt5:使用 QObject 和 QThread 时出现 AttributeError

如何在 Qt c++ 中管理 QThread?

Qt多线程-QThread

单独的 QThread 中的串行端口