Use QtConcurrent::mapped()
and a QFutureWatcher
so that all processing occurs asynchronously.
QFutureWatcher
emits a finished()
signal when all processing is complete. Results are accumulated by a single QFuture
which is managed by the QFutureWatcher
. Most importantly, the UI never freezes.
my_project.pro:
# must include "concurrent" to use QtConcurrent::mapped()
QT += concurrent
...
MappedProcessor.h:
#include <QObject>
#include <QFutureWatcher>
#include <vector>
class MappedProcessor : public QObject
{
Q_OBJECT
public:
explicit MappedProcessor(QObject *parent = nullptr);
public slots:
void processValues();
private slots:
void handleProcessingFinished();
private:
static double myFunction(double value);
QFutureWatcher<double> m_futureWatcher;
};
MappedProcessor.cpp:
#include "MappedProcessor.h"
#include <QtConcurrent/QtConcurrent>
#include <QList>
#include <QThread>
MappedProcessor::MappedProcessor(QObject *parent) : QObject(parent)
{
connect(&m_futureWatcher, &QFutureWatcher<double>::finished,
this, &MappedProcessor::handleProcessingFinished);
}
void MappedProcessor::processValues()
{
// create some values to process
std::vector<double> parameters;
for (auto i = 0; i < 16; ++i)
parameters.push_back(i);
auto sequence = QVector<double>::fromStdVector(parameters);
auto future = QtConcurrent::mapped(sequence, myFunction);
m_futureWatcher.setFuture(future);
}
void MappedProcessor::handleProcessingFinished()
{
// convert the results to std::vector<double>
auto theResults = m_futureWatcher.future().results().toVector().toStdVector();
qDebug() << "Received" << theResults.size() << "results";
}
// pretend to be a long running calculation...
double MappedProcessor::myFunction(double value)
{
QThread::msleep(10000);
return value;
}