Как сделать часть функции отдельным потоком?
Возможно изобретаю велосипед, хочется узнать все ли корректно (возможно у моей реализации не все учтено), или можно лучше, проще?
Есть ф-ция MainWindow::someSlot, где определенную часть (MainWindow::veryLongFunc) необходимо делать отдельным потоком, чтобы интерфейс не зависал.
#mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
int otherFields() const;
void setOtherFields(int otherFields);
public slots:
void someSlot();
private:
void veryLongFunc();
Ui::MainWindow *ui;
int _otherFields;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtConcurrent>
#include <future>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
}
void MainWindow::someSlot() {
/* some code */
QFuture<void> t = QtConcurrent::run([this] { veryLongFunc(); });
while(!t.isFinished()) {
QApplication::processEvents();
}
/* some code */
}
void MainWindow::veryLongFunc() {
/* very long func */
}
int MainWindow::otherFields() const
{
return _otherFields;
}
void MainWindow::setOtherFields(int otherFields)
{
_otherFields = otherFields;
}
MainWindow::~MainWindow() { delete ui; }
Ответы (1 шт):
Не надо делать while(!t.isFinished()) {} - вы тормозите главный поток приложения (со всем его GUI) до тех пор, пока поток функции не выполнит свою работу.
Как я указал в комментарии, вам нужно воспользоваться классом QFutureWatcher, который просигнализирует нам об завершении выполнения функции в потоке.
Заведите объект класса QFutureWatcher в MainWindow:
class MainWindow : ... {
private:
QFutureWatcher<void> _watcher;
}
В конструкторе MainWindow:
MainWindow::MainWindow():... {
connect(&_watcher, &QFutureWatcher<void>::finished, [&](){
qDebug() << "VeryLongFunction's job is done!";
});
}
Далее:
void MainWindow::someSlot() {
QFuture<void> t = QtConcurrent::run([this] { veryLongFunc(); });
_watcher.setFuture(t);
}
Таким образом, вы избежите отсутствия отклика от GUI во время работы ОченьДлиннойФункции