1

I need to load a big file which is an .zip archive and contains two files: config and data. The loading progress consists of three stages: parse config, parse data, map data to more appropriate format. I need to do it in a separate thread. Also I need to display the progress and the stage in the progress dialog which contains QLabel for stage and QProgressBar for current stage progress.

After some studying of QtConcurrent I going to use code like this:

class OscillogramLoader : public QtConcurrent::ThreadEngine<Data>
{
public:
    OscillogramLoader(QString filename);
protected:
    QtConcurrent::ThreadFunctionResult threadFunction() override;
private:
    QString m_filename;
};

QtConcurrent::ThreadFunctionResult OscillogramLoader::threadFunction()
{
    futureInterfaceTyped()->setProgressRange(0, 50);

    for (int i = 0; i < 50; ++ i)
    {
        if (isCanceled())
            break;
        futureInterfaceTyped()->setProgressValueAndText(i, "Parsing config");

        QThread::msleep(100); // Real work will be here
    }

    futureInterfaceTyped()->setProgressRange(50, 250);

    for (int i = 0; i < 200; ++ i)
    {
        if (isCanceled())
            break;
        futureInterfaceTyped()->setProgressValueAndText(50 + i, "Map data");

        QThread::msleep(50); // Real work will be here
    }

    futureInterfaceTyped()->setProgressRange(250, 350);

    for (int i = 0; i < 100; ++ i)
    {
        if (isCanceled())
            break;
        futureInterfaceTyped()->setProgressValueAndText(250 + i, "Map data");

        QThread::msleep(80); // Real work will be here
    }

    reportResult(new OscillogramData()); // returning loaded data

    return QtConcurrent::ThreadFinished;
}

....
QFutureWatcher<OscillogramData>* watcher = new QFutureWatcher<OscillogramData>();
QObject::connect(watcher, &QFutureWatcher<OscillogramData>::started, ...);
QObject::connect(watcher, &QFutureWatcher<OscillogramData>::progressRangeChanged, ...);
QObject::connect(watcher, &QFutureWatcher<OscillogramData>::progressTextChanged, ...);
QObject::connect(watcher, &QFutureWatcher<OscillogramData>::progressValueChanged, ...);
QObject::connect(watcher, &QFutureWatcher<OscillogramData>::finished, [=](){
    OscillogramData data = watcher->result();
    showData(&data);
    watcher->deleteLater();
});
watcher->setFuture(QFuture<OscillogramData>(
    QtConcurrent::startThreadEngine(new OscillogramLoader("/home/example/test1.zip"))));
....

Is it ok?

My old version of the loader class is inherited from QThread, has progressChanged, done, failure signals and overrided run method. Is it better or worse then previous code?

class OscillogramLoader : public QThread
{
    Q_OBJECT
public:
    explicit OscillogramLoader(QString filename, QObject* parent = nullptr);

    QString filename() const;
    bool isCanceled() const;

public slots:
    void cancel();

signals:
    void progressChanged(QString stage, double parcent);
    void done(QString filaname, QSharedPointer<OscillogramData> data);
    void failure(LoadFailureException exception);

protected:
    void run() override;

private:
    QString m_filename;
    bool m_cancelled;
};
Divano
  • 583
  • 5
  • 12
  • 1
    There is no need for QtConcurrent here. You can have just a worker thread for any kind of IO and send signals to UI thread from there. https://stackoverflow.com/questions/35673201/qt-5-update-qprogressbar-during-qthread-work-via-signal – Alexander V Apr 18 '18 at 13:56
  • 1
    Possible duplicate of [Qt 5 : update QProgressBar during QThread work via signal](https://stackoverflow.com/questions/35673201/qt-5-update-qprogressbar-during-qthread-work-via-signal) – Alexander V Apr 18 '18 at 13:58
  • What if I have few Loader classes? QFutureWatcher seems to be very handy because it has signals for monitoring the progress. Should I write my own base class with this signals and inherit it for each loader or inherit QtConcurrent::ThreadEngine? – Divano Apr 18 '18 at 14:29
  • 1
    @AlexanderV Manual thread management is often wasteful. Having a thread pool dedicated to I/O work is quite sensible. – Kuba hasn't forgotten Monica Apr 18 '18 at 15:12
  • @KubaOber the task is plain and simple. But of course dealing with massive parallelism etc. may get an advantage of better abstractions. – Alexander V Apr 18 '18 at 15:47

0 Answers0