1. 程式人生 > >在 QT UI 程式設計中使用 QtConcurrent 和 QFutureWatcher 執行併發任務

在 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