UI 在 QT c++ 中程序为 运行 时阻塞

UI blocks while the program is running in QT c++

我在 ui 中有一个 QT 应用程序。而且我的计算量很大。当计算开始时,我的程序在计算 运行 时停止响应。我想通过多线程来做到这一点,但我不能正确地实现它。我尝试使用默认的 lib 线程来做到这一点:

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);
}

可是,th.join()写到哪里呢?如果我把它放在下一行,它就没有意义了。那么,您有什么建议吗?

更新

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

请参阅 Qt 中的 Multithreading Technologies 文章 - “最简单”的解决方案可能是使用 QtConcurrent 进行 运行 计算,并使用 QFutureWatcher 获得通知计算完成。

所以。类似的东西:

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
}

通过上述实现,您不需要自己的 QThread 对象,因此也不需要对其调用 join。不过,当线程完成时您会收到通知(在上面的示例中调用了函数 computationFinished),因此您可以向用户显示计算结果。

旁注:当然,您需要将 void computationFinished(); 添加到 class 声明中(除非您在其他地方需要它,在 private slots: 部分)。