什么是QFutureWatcher?
QFutureWatcher允许使用信号与槽监控QFuture;QFutureWatcher提供了关于QFuture中通知和信息函数。通过setFuture设置关注的QFuture。
什么是QFuture?
未来的预测?
QFuture类代表着异步计算的结果。为了开始一个计算。我们需要使用Qt Concurrent框架中几个api接口中一个。
QFuture允许线程根据一个至多个当前稍后的结果进行同步,结果的类型须具有构造函数和拷贝构造函数。某一刻上调用result(),resultAt(),results()函数,对获得产生的结果,QFuture将会阻塞直到获得结果。可以调用isResultReadyAt()函数判断当前是否取得结果。对那些可以返回多个结果的,可以通过调用resultCount()函数当前连续的结果。能够从索引0到resultCount()之间迭代结果是安全的。
什么是Qt Concurrent?
QtConcurrent(并发)命名空间提供了高级api接口,使得不使用低级线程原子操作(互斥锁,信号量)编写多线程函数变得可能。通过Qtcurrent编写多线程程序自动调整线程的数量,线程的多少依赖于处理器核心数。这意味着当前的程序能够在未来多核处理器上运行。
API举例:
QtConcurrent::map() applies a function to every item in a container, modifying the items in-place.
为每一个在容器中的item项传递到一个函数中,适当的修改item项。
QFutureWatcher介绍:
在QFutureWatcher中涉及与QFuture函数相关有:
QFutureWatcher: progressValue(), progressMinimum(), progressMaximum(), progressText(), isStarted(), isFinished(), isRunning(), isCanceled(), isPaused(), waitForFinished(), result(), and resultAt().
QFutureWatcher也提供槽函数:
The cancel(), setPaused(), pause(), resume(), and togglePaused()
涉及状态变化的信号函数有:
started(), finished(), canceled(), paused(), resumed(), resultReadyAt(), and resultsReadyAt();
涉及进度信息的信号有:
progressRangeChanged(), void progressValueChanged(), and progressTextChanged()
通过调用setPendingResultLimit函数可以实现节流控制,当resultReadyAt()以及 resultsReadyAt()的信号挂起的个数超过限制时,涉及future的计算将自动的停止。
一旦挂起的信号低于了限制,将恢复运行。
例如:开始一个计算并且完成时回调一个函数。
#ifndef SSS_H
#define SSS_H
#include "QObject"
#include "QDebug"
class MyClass:public QObject
{
Q_OBJECT
public:
void handleFinished()
{
for(int i =0 ;i < 10;i++)
{
qDebug() << "handleFinished:" << i << endl;
const int work = 1000 * 1000 * 400;
volatile int v = 0;
for (int j = 0; j < work; ++j)
++v;
}
}
};
#endif // SSS_H
#include <QtWidgets>
#include <QtConcurrent>
#include "sss.h"
#include <functional>
using namespace QtConcurrent;
int finished(void)
{
qDebug() << "finish" << endl;
return 0;
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
// Instantiate the objects and connect to the finished signal.
MyClass myObject;
QFutureWatcher<int> watcher;
QObject::connect(&watcher, &QFutureWatcher<int>::finished, &myObject, &MyClass::handleFinished);
std::function<int(void)> func = finished;
// Start the computation.
QFuture<int> future = QtConcurrent::run(func);
watcher.setFuture(future);
watcher.waitForFinished();
qDebug() << "Canceled?" << watcher.future().isCanceled();
app.exec();
}
执行结果:
举例:
官方进度条
Random access iterators can be faster in cases where Qt Concurrent is iterating over a large number of lightweight items, since they allow skipping to any point in the container. In addition, using random access iterators allows Qt Concurrent to provide progress information trough QFuture::progressValue() and QFutureWatcher::progressValueChanged().
适用随机访问的迭代能够允许Qtcurrent提供进度信息,可以通过Qfuture::progressValue()以及QfutureWatcher::progressValueChanged();
异步示例:
执行一个耗时长过滤奇数字运算,通过QfutureWatch更新进度。
异步示例代码:
#include "QFutureWatcher"
#include "QFuture"
#include "QProgressDialog"
#include <QApplication>
#include <QtConcurrent>
using namespace QtConcurrent;
bool isEvenNumber(const int & num)
{
//delay
const int work = 1000 * 1000 *10;
volatile int v = 0;
for (int j = 0; j < work; ++j)
++v;
qDebug() << "Number:" << num;
if(num % 2 != 0)
{
return false;
}
else
{
return true;
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
int nums = 1000;
QList<int> list;
for(int i = 0; i<nums ;i ++)
{
list << i;
}
QProgressDialog progress_dig;
QFutureWatcher<void> watch;
//关联设置进度条范围
QObject::connect(&watch,&QFutureWatcher<void>::progressValueChanged,&progress_dig,&QProgressDialog::setValue); QObject::connect(&watch,&QFutureWatcher<void>::progressRangeChanged,&progress_dig,&QProgressDialog::setRange);
std::function<bool(const int &)> func = isEvenNumber;
QFuture<void> future = QtConcurrent::filter(list,func);
watch.setFuture(future);
progress_dig.exec();
watch.waitForFinished();
return a.exec();
}
异步执行结果: