"Зависает" окно QProgressDialog при взаимодействии с запущенным вторичным потоком
QProgressDialog
используется для отображения результатов объёмного расчёта, запущенного в отдельном потоке. Причём объект QProgressDialog
создаётся в основном потоке приложения
// Создаём окно диалога для отображения состояния расчёта
QProgressDialog *progressDialog = new QProgressDialog("Выполняется расчёт...", "&Отмена", 0, 10, mainWindow, Qt::WindowFlags() | Qt::WindowStaysOnTopHint);
progressDialog->setWindowTitle("Подождите");
progressDialog->setAutoReset(false);
progressDialog->setMinimumDuration(0);
progressDialog->show();
connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancel_work()) );
// Создаём нить кода для расчёта
ThreadSetExactData *threadSetExactData = new ThreadSetExactData(..., progressDialog);
connect(threadSetExactData, SIGNAL(finished()), threadSetExactData, SLOT(work_done()));
connect(threadSetExactData, SIGNAL(finished()), threadSetExactData, SLOT(deleteLater()));
threadSetExactData->start();
threadSetExactData->setPriority(QThread::HighestPriority);
Поток взаимодействует с диалогом с помощью механизма сигналов и слотов
class ThreadSetExactData : public QThread
{
Q_OBJECT
public:
explicit ThreadSetExactData(..., QProgressDialog *_progressDialog, QObject *parent = nullptr);
~ThreadSetExactData();
protected:
void run() override;
private slots:
void work_done();
private:
QProgressDialog *progressDialog;
signals:
void set_progress_maximum(int maximum);
void set_progress_value(int value);
};
ThreadSetExactData::ThreadSetExactData(..., QProgressDialog *_progressDialog, QObject *parent) : QThread(parent), progressDialog(_progressDialog)
{
...
connect(this, SIGNAL(set_progress_maximum(int)), progressDialog, SLOT(setMaximum(int)));
connect(this, SIGNAL(set_progress_value(int)), progressDialog, SLOT(setValue(int)));
}
void ThreadSetExactData::run()
{
TotalWork = work();
emit set_progress_maximum(TotalWork);
...
while(have_something_to_do())
{
...
CurrentWork = current_iteration_work();
emit set_progress_value(CurrentWork);
}
}
Взаимодействие работает нормально (сигналы потока эмитируются и обрабатываются), но только окно диалога не воспринимает действие пользователя, в частности, нажатие на кнопку Cancel
. Окно вообще не воспринимает события, кнопка Cancel
"зависает", и, следовательно, никак не эмитирует сигнал canceled()
. Что довольно странно, т.к. диалог запущен в основном потоке и как будто на нём должен действовать цикл обработки событий основного приложения.
В чём может быть проблема?