在 QT UI 编程中使用 QtConcurrent 和 QFutureWatcher 执行并发任务

  • 问题
  • 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 
#include 

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 
#include 
#include 

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

你可能感兴趣的:(QT)