我有一个包含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不会冻结。
我创造了一个新课程" WorkerThread"使用Qt的官方文档,看起来像:
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;
}
我现在如何在run()
中实施WorkerThread
?我可以简单地写一下:
void WorkerThread::run(data *m_data)
{
m_optimization.timeConsumingMethod(m_data);
emit finished();
}
还是我必须在timeConsumingMethod
中复制run()
的整个定义?为什么/为什么不呢?
答案 0 :(得分:2)
您不需要进行任何明确的线程管理,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(®, &ctl);
reg.show();
return app.exec();
}
#include "main.moc"