QThread C 中的基本用途

QThread Basic use in c++

本文关键字:QThread      更新时间:2023-10-16

我有一个包括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移至单独的线程中,而不是主线程,以使GUI在timeConsumingMethod运行时不会冻结。我使用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();
}

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

您不需要执行任何明确的线程管理,QT已经为您做。使用QtConcurrent::run从线程池中的工作线程中进行工作。

您还应该将管理工作的控制器和UI解除。这些对象的知识应与对象本身分开。这允许在UI和控制器的设计中更灵活,并有助于避免从错误的线程访问非线程安全方法的几类错误。

完成示例:

// https://github.com/KubaO/stackoverflown/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_data{new 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_layout{this};
   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 app{argc, argv};
   Controller ctl;
   Registration reg;
   setup(&reg, &ctl);
   reg.show();
   return app.exec();
}
#include "main.moc"