在 QT UI 編程中使用 QtConcurrent 和 QFutureWatcher 執行併發任務

問題

在 QT 的 UI 編程中, 如果有一個函數消耗的時間特別長, 並且運行於主線程, 那麼界面的響應會很不靈敏. 通常的作法是使用多線程編輯.

另外, 如果該函數執行時間很長, 爲了通知任務的進度, 一般會使用進度條. 但有時候無法準確的使用進度條, 比如在數據庫操作中, 爲了提高讀寫數據庫的性能, 通常會採用事務操作, 多個讀寫數據庫的操作合併成了一個事務, 此時如何設置進度條的進度值?

此時, 可以使用 QtConcurrent 和 QFutureWatcher 來解決這個問題. 對於第一個問題不需多言. 對於第二個問題, 可以在任務開始後以QMessageBox::imformation 對話框來告知用戶完成任務需要時間很長, 在任務執行完畢時關閉該對話框 (如果用戶沒有關閉的話).

QtConcurrent 和 QFutureWatcher

QtConcurrent 是一個名字空間, 其內包含了衆多的高級 API, 方便用戶編寫多線程程序.

QFutureWatcher 可以用於監視線程的完成情況, 並獲取線程的返回值.
QtConcurrent 線程函數與 QFutureWatcher 之間的中間者是 QFuture.

示例代碼

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFutureWatcher>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    //
    void busy_job();

private:
    //
    int do_busy_job();

    //
    void busy_job_finished();

private:
    Ui::MainWindow *ui;

    //
    QFutureWatcher<int>* watcher_;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QtConcurrent>
#include <QFuture>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //
    watcher_ = new QFutureWatcher<int>;
    connect(watcher_, &QFutureWatcher<int>::finished,
            this, &MainWindow::busy_job_finished);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::busy_job()
{
    // 若有需要, 啓動告知對話框

    auto future = QtConcurrent::run(this, &MainWindow::do_busy_job);
    watcher_->setFuture(future);
}

int MainWindow::do_busy_job()
{
    return 1;
}

void MainWindow::busy_job_finished()
{
    // 若有需要, 關閉通知對話框

    qDebug() << "busy job finished!";
    qDebug() << "the returned value is: "
             << watcher_->result();
}

調用

MainWindow w;
w.busy_job();

輸出

busy job finished!
the returned value is:  1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章