您当前的位置: 首页 > 

龚建波

暂无认证

  • 2浏览

    0关注

    313博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

QFuture的使用:多线程与进度条

龚建波 发布时间:2020-06-25 15:10:11 ,浏览量:2

介绍

QFuture 类可以用来获取异步计算的结果(类似 std::future ),一般配合 Qt Concurrent 模块和 QFutureWatcher 类工作。在 Qt Creator 中搜索 concurrent 可以看到一些相关示例。官方示例中, QFuture 一般和 QFutureWatcher 配合,因为 QFuture 不是 QObject 子类,没有信号槽。但是 QFuture 相关的接口会触发 QFutureCallOutEvent 事件,QFutureWatcher 接收该事件后发送对应信号。

相关类的对应基本介绍:

  • QFuture:表示异步计算的结果
  • QFutureWatcher:QFuture本身不带信号槽,可使用QFutureWatcher进行监控
  • QFutureInterface:该类没有提供文档,出现于Qt源码。QFuture与QFutureInterface的关系类似std::future与std::promise(Qt6中基于QFutureInterface封装了一个QPromise类)。QFutureInterface可用于生成QFuture,在Qt类实现中,QFuture持有一个QFutureInterface成员。

从目前的文档和示例来看,QFuture 主要是由 Qt Concurrent 的相关接口生成,一般操作如下:

//concurrent生成future
QFuture future = QtConcurrent::run([this]{ /**/ });

//future设置给watcher进行监控
QFutureWatcher theWatcher;
theWatcher.setFuture(future);

//future对应的操作结束,触发watcher信号
connect(&theWatcher,&QFutureWatcher::finished,this,[this]{ /**/ });

本文的需求是实现一个展示多线程处理进度的进度条,但 QFuture 只有获取状态值的接口,而没有设置状态值的接口,这些都被封装在了 QFutureInterface 中。要实现需求,需要创建一个 QFutureInterface 对象,并用他来生成一个相关联的 QFuture 对象,再设置给 QFutureWatcher 进行监测,在线程中我们操作 QFutureInterface 实例就能触发 QFutureWatcher 对应的信号。

功能实现

实现效果(GIF):

完整代码链接(GitHub):MyTestCode/Qt/TestQt_20200625_QFuture at master · gongjianbo/MyTestCode · GitHub

主要实现代码(组件是在 ui 上拖的):

(其实这里遇到一个问题,就是调用 cancel 来取消的话,会异常结束或者卡死,所以暂时用的 pause 来结束,线程中判断是否 pause。还要注意一个问题是,pause 或者 cancel 后,后续的设置是不会触发信号的,所以我在线程中结束了pause。)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
//QFuture类表示异步计算的结果
#include 
//QFuture本身不带信号槽,可使用QFutureWatcher进行监控
#include 
//QFutureInterface没有提供文档,出现于Qt源码
//QFuture与QFutureInterface的关系类似std::future与std::promise
//QFutureInterface可用于生成QFuture
//在Qt类实现中,QFuture持有一个QFutureInterface成员
#include 

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    //QFuture本身不带信号槽,可使用QFutureWatcher进行监控
    QFutureWatcher myWatcher;
};
#endif // MAINWINDOW_H

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

#include 

#include 
#include 

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

    connect(ui->btnStart,&QPushButton::clicked,[this](){
        qDebug()            
关注
打赏
1655829268
查看更多评论
0.0387s