-1

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
  • A `std::thread` (object) is not the same as a thread (computing concept). The thread spawned by `thread th(HeavyCalculations);` still persists even when `th` goes out of scope. There's nothing in the code shown that indicates any blocking would occur. My best guess (and it's only a guess) is that you have some resource acquired in your `HeavyCalculations` function that blocks progress in your UI thread. – JohnFilleau Apr 13 '22 at 19:04
  • Have you tried reading the [docs](https://doc.qt.io/qt-5/threads-technologies.html)? – JarMan Apr 13 '22 at 19:05
  • 2
    This is a duplicate of your [previous question](https://stackoverflow.com/questions/71862005/how-to-implement-multithreading-correctly-in-qt-c). Did you read the [link](https://stackoverflow.com/questions/40284850/qthread-vs-stdthread) provided there? – G.M. Apr 13 '22 at 19:05
  • 1
    why are you editing in parts of the answer into your question? If you have new questions arising, post new questions, instead of changing your question so that the original question isn't even in there anymore... – codeling Apr 14 '22 at 10:19

1 Answers1

2

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).

codeling
  • 11,056
  • 4
  • 42
  • 71
  • This solution gives error: Out-of-line definition of 'computationFinished' does not match any declaration in 'MainWindow' – Ростислав Романец Apr 14 '22 at 09:40
  • you didn't show the declaration of the class, so I didn't show the declaration of `computationFinished` ;) Joking aside, of course, you have to add `void computationFinished();` to your class declaration - it can be in the `private` section. – codeling Apr 14 '22 at 09:43
  • I added this to the header file but now I have another error. I have added the header file to my question, you can have a look. Error: Reference to non-static member function must be called; did you mean to call it with no arguments? (fix available) – Ростислав Романец Apr 14 '22 at 09:56
  • and to which line does this error point? – codeling Apr 14 '22 at 09:59
  • probably to the containing `QtConcurrent::run`? Could you also show the declaration of `HeavyCalculations` function? – codeling Apr 14 '22 at 10:00
  • Error in this line: QObject::connect(futureWatcher, &QFutureWatcher::finished, this, computationFinished). I've updated the question so my function declaration is now visible. – Ростислав Романец Apr 14 '22 at 10:08
  • ah yes an error slipped in there. corrected now. you might have guessed by looking at the other connect call how the 4th argument should have looked like... – codeling Apr 14 '22 at 10:10