版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Amnes1a/article/details/65630701
在Qt中,为我们提供了好几种使用线程的方式,除了最基本的QThread类之外,还有QRunnable抽象类,类似于Java的runnable接口,还可以使用moveToThread() 函数,还有更高级的QtConcurrent框架。而今天,我们要看的QFuture就是和QtConcurrent框架API配合使用的一个类。新来看Qt帮助文档对这个类的详细介绍。

QFuture类用来表示一个异步计算的结果,而该异步计算通常就是由Qt Concurrent框架中的相关函数开启的。QFuture允许线程同步的获得一个或多个在将来某个时间点才准备好的结果。这些结果可以是任何具有默认构造函数和拷贝构造函数的类型。如果在调用该类的result()、resultAt() 或 results() 函数时,某个结果还不可用,QFuture会等待直到该结果可用,即可得到。当然,你也可以使用isResultReadyAt() 函数来判断某个结果是否已经准备好了。对于那些要获得多个结果的QFuture对象来说,resultCount() 函数会返回可以得到的连续结果的个数。这也意味着,我们在0和resultCount() 之间对QFuture对象进行遍历,总是安全的。并且,处理使用刚才说的下标外,QFuture还提供了Java类型的和STL类型的迭代器供我们使用。

使用QFuture对象,我们也可以和正在运行中的异步计算进行交互。例如,可以使用cancel() 函数取消一个异步计算;使用setPaused()、pause()、resume()、或者 togglePaused() 函数暂停一个异步计算。但要记住,并不是所有的异步计算都能被取消或暂停。例如,QtConcurrent()::run() 方法返回的future不能被取消,但是QtConcurrent::mappedReduced() 函数返回的future就可以。

除了刚才说的暂停操作,我们还可以获得异步计算的当前进度信息,progressValue()、progressMinimum()、progressMaximum()和progressText() 函数可以帮我们提供这些信息。

一个比较重要的函数就是waitForFinished(),该函数会导致调用线程阻塞来等待异步计算结束,以确保所有的结果都是可用的。

上面讲到,我们可以手工的暂停或取消一个异步计算,相对的,QFuture也为我们提供了查询当前计算状态的方法。比如,isCanceled(),isStarted(),isFinished(),isRunning()和 isPaused()函数。

QFuture是一个轻量级的引用计数类,所以它可以被当做参数值传递。

其实,在构建QFuture的对象时,我们会同时指定一个模板参数,表示QFuture要处理的结果的类型。其中,QFuture<void>是一个特化的不包含获取结果函数的QFuture对象。内可以将一个QFuture<void>对象赋值给一个QFuture<T>对象,反过来亦可。这对于那些只关注异步计算的状态或进度信息,而不关注实际结果的QFuture对象来说是及其有用的。

但这个类不支持信号和槽,若想使用信号和槽来和异步计算进行通信,需要使用QFutureWatcher类。

下面,我们再来看一下QFuture类中常用的一些函数。

QFuture::QFuture()
QFuture::QFuture(const QFuture &other)
QFuture::~QFuture()
构造函数到没什么好说的,一般使用第一个就好,构造一个QFuture对象,然后用该对象接收QtConcurrent::run() 或 QtConcurrent::mappedReduced()之类的函数的返回值即可。
但我们要记住,当QFuture对象析构时,既不会等待也不会取消异步计算。我们应该使用waitForFinished() 或者 QFutureSynchronizer类还确保在该对象析构之前所有的异步计算都完成。

void QFuture::cancel()
取消该对象代表的异步计算。但请注意,该取消动作也是异步的。如果想同步等待取消完成,要在调用cancel() 函数后,调用一下waitForFinished() 函数。
被取消的future对象,我们仍然可以从中提取到已经可用的结果,但是,在调用cancel() 之后,不会再有新的结果变的可用,而该future对象上的所有QFutureWatcher对象都不会在向我们传送进度信息和结果可用的信号。

再次重申,不是所有的异步计算都可以取消。参看上面已经说过的。

bool QFuture::isCanceled() const
判断异步计算是否被cancel() 函数取消了,但要注意,我们在上面讲cancel() 函数的时候就说过,cancel动作是异步,也就是说当这个函数返回true的时候,异步计算可能还在运行。
void QFuture::pause()
暂停当前future对象代表的异步计算。等价于setPaused(true)
bool QFuture::isPaused() const
判断一个异步计算是否被pause() 函数暂停了。同样,暂停动作也是异步的。

至于其他的成员方法,也都非常容易理解,见名知意,大家在使用时,具体参考Qt帮助文档即可。
上面我们说到,QFuture在取得异步结果方面除了提供了相关的result() 函数,还提供了方便的迭代器类,既有STL风格的QFuture::const_iterator,也有Java风格的QFutureIterator类。其中,STL风格的迭代器和STL中容器的迭代器一样,重载了*和->运算符,以及其他常用的++,--等运算符。而Java风格的迭代器则提供了hasNext()、next()等函数。下面我们分别来看看。

STL风格的迭代器,即QFuture::const_iterator,我们可以定义一个该类型的变量,然后使用QFuture::constBegin() 进行初始化。如下代码所示:

QFuture<QString> future = ...;

QFuture<QString>::const_iterator i;
for (i = future.constBegin(); i != future.constEnd(); ++i)
cout << *i << endl;
同样,对于Java风格的迭代器来说,由于其是一个c++类,所以其构造函数接受一个要进行迭代的QFuture对象,然后使用next() 函数进行逐个遍历。例如以下代码所示:

QFuture<QString> future;
...
QFutureIterator<QString> i(future);
while (i.hasNext())
qDebug() << i.next();
除了next()方法外,QFutureIterator类还提供了previous() 函数,可以完成从后想起的反向遍历。如下代码所示:

QFutureIterator<QString> i(future);
i.toBack();
while (i.hasPrevious())
qDebug() << i.previous();

下面,我们就来写一个使用QFuture的简单例子。因为我们还没讲到QtConcurrent框架及其API,所以,我们就简单的用一下QtConcurrent::run()方法,来启动一个函数,在此函数中计算第100个斐波那契数。代码如下:

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

//计算第lindex 个 斐波那契数值
qulonglong Fibonacci(int index)
{
qulonglong f1 = 1, f2 = 1, cur = 0;
for(int i = 3; i <= index; i++)
{
cur = f1 + f2;
f1 = f2;
f2 = cur;
}
return cur;
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QFuture<qulonglong> future = QtConcurrent::run(Fibonacci, 100);
//future.waitForFinished();
qDebug() << "test";
qDebug() << future.result();

return a.exec();
}

在此,我们通过使用run()方法,就启动了一个异步计算,紧接着我们调用result() 函数,取得该异步计算的结果。如果此时该结果还不可用,那么调用该函数会是函数阻塞等待结果。当然,我们也可以先调用waitForFinished() 等待其运行结束。其输出结果如下:

先打印出 “test” 字符串,可见,我们通过run() 启动的Fibonacci() 函数确实是异步执行的,并没有阻塞我们的main函数的执行流程。

另外,QtConcurrent在Qt中是一个独立的命名空间,所以还要在.pro文件中引入该模块。如下:

QT += core concurrent

至于QtConcurrent中的其他函数及其相关类,会在后续博文中讲解。

再上面的例子中,我们只是使用QtConcurrent::run()开启了一个异步计算,然后调用QFuture::result() 等待计算的结果。但其实同一时间,我们可以同时开启多个并行运行的异步计算,然后分别使用一个QFuture对象等待结果。但其实在Qt中,为了简化多个QFuture的同步等待操作,特地为我们提供了一个模板类QFutureSynchronizer。该类为我们提供了 addFuture()和setFuture()函数,我们可以使用这两个函数,将代表多个异步计算的QFuture对象添加到一个QFutureSynchronizer对象中,然后调用该类的waitForFinished()方法,该方法就是用来等待所有的QFuture结束。

简单使用例子如下:

void someFunction()
{
QFutureSynchronizer<void> synchronizer;
synchronizer.addFuture(QtConcurrent::run(anotherFunction));
synchronizer.addFuture(QtConcurrent::map(list, mapFunction));

return; // 等待所有的异步计算结束才返回
}
除了等待函数外,QFutureSynchronizer类还提供了一setCancelOnWait()方法,若通过这个函数设置了cancel-on-wait标志,那么调用waitForFinished()函数会取消所有未完成的计算。
下面,我们在上面求斐波那契数的例子中,再开启一个异步计算,同时求出两个斐波那契数

#include <QCoreApplication>
#include <QFuture>
#include <QFutureSynchronizer>
#include <QtConcurrent>
#include <QDebug>

//计算第lindex 个 斐波那契数值
qulonglong Fibonacci(int index)
{
qulonglong f1 = 1, f2 = 1, cur = 0;
for(int i = 3; i <= index; i++)
{
cur = f1 + f2;
f1 = f2;
f2 = cur;
}
return cur;
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

QFutureSynchronizer<qulonglong> synchronizer;
synchronizer.addFuture(QtConcurrent::run(Fibonacci, 50));
synchronizer.addFuture(QtConcurrent::run(Fibonacci, 100));
synchronizer.waitForFinished();
qDebug() << "第50个斐波那契数: " << synchronizer.futures()[0].result();
qDebug() << "第100个斐波那契数: " << synchronizer.futures()[1].result();

return a.exec();
}

运行结果如下:

---------------------
作者:求道玉
来源:CSDN
原文:https://blog.csdn.net/Amnes1a/article/details/65630701
版权声明:本文为博主原创文章,转载请附上博文链接!

使用QFuture类监控异步计算的结果的更多相关文章

  1. java异步计算Future的使用(转)

    从jdk1.5开始我们可以利用Future来跟踪异步计算的结果.在此之前主线程要想获得工作线程(异步计算线程)的结果是比较麻烦的事情,需要我们进行特殊的程序结构设计,比较繁琐而且容易出错.有了Futu ...

  2. Task:取消异步计算限制操作 & 捕获任务中的异常

    Why:ThreadPool没有内建机制标记当前线程在什么时候完成,也没有机制在操作完成时获得返回值,因而推出了Task,更精确的管理异步线程. How:通过构造方法的参数TaskCreationOp ...

  3. Knockout v3.4.0 中文版教程-5-计算监控-使用计算监控

    3. 计算监控 1.使用计算监控 如果你有一个监控的属性firstName和另一个lastName,但你想显示全名怎么办? 这就是引入计算监控的原因-这是依赖于一个或多个其他的observables函 ...

  4. C++类的大小计算汇总

    C++中类涉及到虚函数成员.静态成员.虚继承.多继承.空类等. 类,作为一种类型定义,是没有大小可言的. 类的大小,指的是类的对象所占的大小.因此,用sizeof对一个类型名操作,得到的是具有该类型实 ...

  5. OpenACC 异步计算

    ▶ 按照书上的例子,使用 async 导语实现主机与设备端的异步计算 ● 代码,非异步的代码只要将其中的 async 以及第 29 行删除即可 #include <stdio.h> #in ...

  6. Math类的数学计算功能

    //Math类的数学计算功能 public class MathTest { public static void main(String[] args) { /*----------下面是三角运算- ...

  7. 13.FutureTask异步计算

    FutureTask     1.可取消的异步计算,FutureTask实现了Future的基本方法,提供了start.cancel 操作,可以查询计算是否完成,并且可以获取计算     的结果.结果 ...

  8. 怎样给ExecutorService异步计算设置超时

    ExecutorService接口使用submit方法会返回一个Future<V>对象.Future表示异步计算的结果.它提供了检查计算是否完毕的方法,以等待计算的完毕,并获取计算的结果. ...

  9. gearman(异步计算)学习

    Gearman是什么? 它是分布式的程序调用框架,可完成跨语言的相互调 用,适合在后台运行工作任务.最初是2005年perl版本,2008年发布C/C++版本.目前大部分源码都是(Gearmand服务 ...

随机推荐

  1. 【Android 开发教程】动态添加Fragments

    本章节翻译自<Beginning-Android-4-Application-Development>,如有翻译不当的地方,敬请指出. 原书购买地址http://www.amazon.co ...

  2. PullToRefresh使用详解(一)--构建下拉刷新的listView

    前言:前几天写了篇关于PullToRefresh控件的DEMO导入的博客,但由于当时没有用到,所以就没细往下讲,现在开始到了实战阶段,用到了PullToRefresh的listView样式,网上有讲的 ...

  3. YUV格式详细解释与FFMPEG的关系

    YUV主要的采样格式 主要的采样格式有YCbCr 4:2:0.YCbCr 4:2:2.YCbCr 4:1:1和 YCbCr 4:4:4.其中YCbCr 4:1:1 比较常用,其含义为:每个点保存一个 ...

  4. Django的自定义标签

    Django提供了自定义标签功能,可以方便常用方法的重复使用. 标签的本质就是函数,标签名就是函数名. 注意点: 1.需要到django.template对象. 2.register = templa ...

  5. apache下用expires_module让浏览器缓存静态文件

    让浏览器缓存CSS.JS.图片.静态文件等是很重要的事情,这样可以减轻服务器的压力,省的浏览器经常要去服务端下载这些静态文件.下面看看配置方法吧. 1.开启apache扩展模块mod_expires. ...

  6. java - day15 - NonameInner

    匿名内部类 public interface Inter {} interface Inter2{ void show(); } main(){ //错误,接口不能实例化 Inter t = new ...

  7. MySQL获取Schema表名和字段信息

    MySQL获取Schema表名和字段信息 获取表名 select TABLE_NAME,TABLE_TYPE,ENGINE,TABLE_ROWS,TABLE_COMMENT,CREATE_TIME,U ...

  8. 收集别人的一些第三方(MARK)

    本文是恢复数据,数据丢失前,原文由 @shiren1118 发表于 2012-12-28,对 Ruby 社区对 iOS 开发感兴趣的朋友来说,非常有价值. iosboilerplate这个选项是比较成 ...

  9. 程序的记事本--log4net

    你是否在遇到程序执行问题时常常百度?你是否在遇到执行错误时常常去询问别人?假设有那么是时候改变啦,对于一个Developer来说那是不专业的表现,专业的Developer都会首先查看程序的执行日志.先 ...

  10. quantz入门和使用流程(转载)

    1.下载地址:http://quartz-scheduler.org/downloads/catalog http://quartz-scheduler.org/downloads/destinati ...