其他分享
首页 > 其他分享> > Qt QtConcurrent多线程 - map、mapped和mappedReduced

Qt QtConcurrent多线程 - map、mapped和mappedReduced

作者:互联网

Qt中的 Concurrent 模块为我们提供了在一个序列容器类型针对每一个元素的多线程并行运算,比如 QList 、 QVector 。


1. map 和 mapped

QtConcurrent::map 和 QtConcurrent::mapped 的基本形式如下:

QFuture<void> map(Sequence &sequence, MapFunctor map)

下面是一个简单的使用示例:

1 void scale(QImage &image)
2 {
3     image = image.scaled(100, 100);
4 }
5 
6 QList<QImage> images = ...;
7 QFuture<void> future = QtConcurrent::map(images, scale);

该示例中,多线程对 QList<QImage> 容器中的每一个 QImage 缩放到 100 * 100 的尺寸。结果会覆盖掉原容器中的元素。


QtConcurrent::mapped 函数跟 QtConcurrent::map 函数类似,不同之处在于:

  1. 传递的函数形式不同。它的形式为, U function(const T &t); ,一个常引用做为参数,表示容器中的元素不可修改。返回值 U 存入整个 QtConcurrent::mapped 计算后的新容器中返回。
  2. 函数 QtConcurrent::mapped 的返回值为 QFuture<U> ,QFuture 除了可以表示单个类型也可以一组序列容器类型,跟单个的类似,可以使用 results 函数返回运算后的结果。

下面是使用 QtConcurrent::mapped 的例子

1 QImage scaled(const QImage &image)
2 {
3     return image.scaled(100, 100);
4 }
5 
6 QList<QImage> images = ...;
7 QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scaled);

这里同样也是对列表中的 QImage 进行缩放到 100 * 100 大小,但是容器本身的内容没有改变。
使用如下代码获取运算结果:

1 funcFunture2.waitForFinished();        // 等待运算处理完成
2 thumbnails.results();                // 获取运算结果

2. mappedReduced

mappedReduced() 类似于 QtConcurrent::mapped() ,但是它不是返回一个带有新结果的序列,而是使用reduce函数将结果组合成一个单独的值。

它的函数基本形式如下:

1 template <typename Sequence, typename MapFunctor, typename ReduceFunctor>
2 QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> 
3 mappedReduced(const Sequence &sequence,
4               MapFunctor map,
5               ReduceFunctor reduce,
6               ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce))

下面是一个示例:

 1 void addToCollage(QImage &collage, const QImage &thumbnail)
 2 {
 3     QPainter p(&collage);
 4     static QPoint offset = QPoint(0, 0);
 5     p.drawImage(offset, thumbnail);
 6     offset += ...;
 7 }
 8 
 9 QList<QImage> images = ...;
10 QFuture<QImage> collage = QtConcurrent::mappedReduced(images, scaled, addToCollage);

这里 images 中的每一个元素执行完 scaled 函数后的序列,序列中的每一个元素再执行函数 addToCollage ,最后将计算结构返回。


3. 其他扩展

使用迭代器作为序列容器的输入范围。

1 QList<QImage> images = ...;
2 
3 QFuture<QImage> thumbnails = QtConcurrent::mapped(images.constBegin(), images.constEnd(), scaled);
4 
5 // map in-place only works on non-const iterators
6 QFuture<void> future = QtConcurrent::map(images.begin(), images.end(), scale);
7 
8 QFuture<QImage> collage = QtConcurrent::mappedReduced(images.constBegin(), images.constEnd(), scaled, addToCollage);

阻塞等待形式

map 、mapped和mappedReduced为非阻塞形式的多线程执行,可以使用 QFuture 和 QFutureWatcher 作异步通知。但是Qt同样也提供了阻塞版本的函数:

1 QList<QImage> images = ...;
2 
3 // each call blocks until the entire operation is finished
4 QList<QImage> future = QtConcurrent::blockingMapped(images, scaled);
5 
6 QtConcurrent::blockingMap(images, scale);
7 
8 QImage collage = QtConcurrent::blockingMappedReduced(images, scaled, addToCollage);

这里需要注意的是,他们的返回值不是 QFuture ,而是真实的结果类型。(在这个示例中,返回 QImage 和 QList<QImage>)

使用类的成员函数

 1 // squeeze all strings in a QStringList
 2 QStringList strings = ...;
 3 QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze);
 4 
 5 // swap the rgb values of all pixels on a list of images
 6 QList<QImage> images = ...;
 7 QFuture<QImage> bgrImages = QtConcurrent::mapped(images, &QImage::rgbSwapped);
 8 
 9 // create a set of the lengths of all strings in a list
10 QStringList strings = ...;
11 QFuture<QSet<int> > wordLengths = QtConcurrent::mappedReduced(string, &QString::length, &QSet<int>::insert);

仿函数

 1 struct Scaled
 2 {
 3     Scaled(int size) : m_size(size) { }
 4     typedef QImage result_type;
 5 
 6     QImage operator()(const QImage &image)
 7     {
 8         return image.scaled(m_size, m_size);
 9     }
10 
11     int m_size;
12 };
13 
14 QList<QImage> images = ...;
15 QFuture<QImage> thumbnails = QtConcurrent::mapped(images, Scaled(100));

对于 reduce 函数,不直接支持函数对象。但是,当显式指定约简结果的类型时,可以使用仿函数:

 1 struct ImageTransform
 2 {
 3     void operator()(QImage &result, const QImage &value);
 4 };
 5 
 6 QFuture<QImage> thumbNails =
 7 QtConcurrent::mappedReduced<QImage>(images,
 8                                     Scaled(100),
 9                                     ImageTransform(),
10                                     QtConcurrent::SequentialReduce);

lambda或使用std::bind,处理多参数函数

比如这个函数

QImage QImage::scaledToWidth(int width, Qt::TransformationMode) const;

可以借助 lambda 表达式处理参数

1 QList<QImage> images = ...;
2 std::function<QImage(const QImage &)> scale = [](const QImage &img) {
3     return img.scaledToWidth(100, Qt::SmoothTransformation);
4 };
5 QFuture<QImage> thumbnails = QtConcurrent::mapped(images, scale);

 

标签:map,QFuture,Qt,QtConcurrent,images,多线程,QImage,函数
来源: https://www.cnblogs.com/ybqjymy/p/14150103.html