Home > other >  UI blocks while the program is running in QT c
UI blocks while the program is running in QT c

Time:04-14

I have an application in QT with ui. And also I have heavy calculations. When calculations starts, my program stops responding while calculations are running. I wanted to do this via multithreading, but I cannot correctly implement this. I tried to do it with default lib thread:

void HeavyCalculations()
{
   // some heavy calculations
}

void MainWindow::on_pushButton_3_clicked()
{
   // context is some object in whose context the finished signal should be called, so most likely your MainWindow
    auto futureWatcher = new QFutureWatcher<void>(this);
    QObject::connect(futureWatcher, &QFutureWatcher<void>::finished, this, compulationFinished);
    QObject::connect(futureWatcher, &QFutureWatcher<void>::finished, futureWatcher, &QFutureWatcher<void>::deleteLater);
    auto future = QtConcurrent::run( PackBytes );
    futureWatcher->setFuture(future);
}

but, where to write th.join()? If I put this in the next line, it won't make sense. So, do you have any suggestions?

UPD

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_3_clicked();
    void compulationFinished();

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

CodePudding user response:

See the Multithreading Technologies article in Qt - the "simplest" solution is probably to use QtConcurrent for running the computation, and QFutureWatcher for getting notified about when the computation is finished.

So. something along those lines:

void MainWindow::on_pushButton_3_clicked()
{
    // context is some object in whose context the finished signal should be called, so most likely your MainWindow
    auto futureWatcher = new QFutureWatcher<void>(this);
    QObject::connect(futureWatcher, &QFutureWatcher<void>::finished, this, &MainWindow::computationFinished);
    QObject::connect(futureWatcher, &QFutureWatcher<void>::finished, futureWatcher, &QFutureWatcher<void>::deleteLater);
    auto future = QtConcurrent::run( HeavyCalculations );
    futureWatcher->setFuture(future);
}

void MainWindow::computationFinished()
{
    // tell the user computation is finished or something
}

With the above implementation, you don't need your own QThread object, and therefore also don't need to call join on it. Still, you are notified when the thread is finished (the function computationFinished is called in the above example), so you can for example show the result of your computation to the user.

Side note: of course you need to add void computationFinished(); to your class declaration (unless you need it somewhere else, in the private slots: section).

  • Related