I am trying to learn how to use Multi-threading in Qt and put it to use in QtWidget applications. So I have setup this simple test case.
MainWindow This form has some buttons and each button will execute another form (a Dialog for that matter).
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnShowCalibrationDialog, &QPushButton::clicked,
this, [&](){
CalibrationDialog dlg;
dlg.exec();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
CalibrationDialog This dialog has a QPushButton
and a QTextEdit
. When the button is clicked I will run a QRunnable class (comes next!)
calibrationdialog.h (I have spared you the includes and guards!)
class CalibrationDialog : public QDialog
{
Q_OBJECT
public:
explicit CalibrationDialog(QWidget *parent = nullptr);
~CalibrationDialog();
public slots:
void onBeginWorkRequested();
void onReceiveData(int data);
private:
Ui::CalibrationDialog *ui;
};
calibrationdialog.cpp
#include "worker.h"
CalibrationDialog::CalibrationDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CalibrationDialog)
{
ui->setupUi(this);
connect(ui->btnBegin, &QPushButton::clicked,
this, &CalibrationDialog::onBeginWorkRequested);
}
CalibrationDialog::~CalibrationDialog()
{
delete ui;
}
void CalibrationDialog::onBeginWorkRequested()
{
qDebug() << "CalibrationDialog::onBeginWorkRequested()" << "on" << QThread::currentThreadId();
Worker* worker = new Worker();
QThreadPool* pool = QThreadPool::globalInstance();
connect(worker, &Worker::reportProgress,
this, &CalibrationDialog::onReceiveData);
pool->start(worker);
pool->waitForDone();
}
void CalibrationDialog::onReceiveData(int data)
{
ui->teResults->append(QString::number(data));
ui->teResults->ensureCursorVisible();
}
Worker And this is some runnable...I want to report the progress so that is shows up in the textedit of the dialog in a reponsive manner!
worker.h
class Worker : public QObject, public QRunnable
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
void run() override;
private:
int mProgress = 0;
signals:
void reportProgress(int progress);
};
worker.cpp
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::run()
{
qDebug() << "Worker is running #" << QThread::currentThreadId();
while(true) {
mProgress += 100;
emit reportProgress(mProgress);
QThread::msleep(500);
}
}
I see in the debugger that control goes in to the while loop...but the signal is not being handled by the dialog! I mean the textedit stays empty!
I tried to read documentationand search online...I came to the conclusion that my problem lies in the waste land of thread affinity....but I have no idea if that is the case and if that is, how to solve it. Please assist!
remove pool->waitForDone();
, never use waitForX methods in a GUI since they are blocking preventing signals from doing their job.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.