QtConcurrent在单独的线程中加载大文件并显示进度

时间:2018-04-18 13:48:12

标签: c++ qt qtconcurrent

我需要加载一个大文件,它是一个.zip存档,包含两个文件:config和data。加载进度包括三个阶段:解析配置,解析数据,将数据映射到更合适的格式。我需要在一个单独的线程中完成它。此外,我需要在进度对话框中显示进度和阶段,其中包含舞台QLabel和当前舞台进度的QProgressBar。

在对QtConcurrent进行一些研究之后,我将使用这样的代码:

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

可以吗?

我的旧版本的loader类继承自QThread,具有progressChanged,done,failure信号和overrided run方法。它比以前的代码更好还是更差?

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

0 个答案:

没有答案