原文链接:packaged_task介绍与实例

  • std::packaged_task<>是一个类模板,代表一个异步任务。封装了
  • 1、可调用实体,即函数,lambda函数或函数对象
  • 2、一个共享状态,通过关联的回调来存储返回的值或抛出的异常。
  • 假设我们有一个现有的函数从数据库中提取数据并返回,
std::string gtDataFromDB(std::string token){//Do some stuff to fetch the datastd::string data = "Data fetched from DB by filter :: + token;return data;
}
  • 现在我们想在一个单独的线程中执行该函数,但是我们如果在其他线程结束的情况下在主线程中获取结果或异常返回?
  • 一种方法是更改函数声明并在函数中传递std::promise。在传递线程函数中的std::promise<>对象之前,将相关的std::future<>从中取出并保存在主线程中。现在,在线程函数返回其值之前,应该在传入的std::promise参数中设置它,所以它可以在主线程的相关std::future对象中使用。
  • 但是,如果我们使用std::packaged_task<>,则可以避免创建std::promise和更改函数代码。

使用packaged_task<>创建异步任务

  • std::packaged_task<>可以包装一个标准函数,使其适用于作为异步功能运行。
  • 当std::packaged_task<>在一个单独的线程中运行时,它会调用相关的回调函数,并将返回值或异常存储在其内部共享状态中。该值可以通过std :: future <>对象在其他线程或主函数中访问。
  • 从上面提到的函数创建一个packaged_task<>,运行于独立的线程并从其future<>对象获取返回值。

创建std::packaged_task<> 对象

  • std::packaged_task<>对象是一个类模板,因此我们需要将模板参数传递给packaged_task<>,即可调用函数的类型。
//创建封装了回调函数的packaged_task<>
std::packaged_task<std::string(std::string)> task(getDataFromDB);
  • 获取future对象
    
//从packaged_task<>获取相关future<>
std::future<std::string> result = task.get_future();

传递packaged_task<>给线程

  • std::packaged_task<>可移动,但是不可复制,所以我们需要将它传递给线程
//传递packaged_task<>给线程以异步运行
std::thread th(std::move(task), "Arg");
  • 由于packaged_task只可以移动,不可以复制,因此我们在将它移动到线程之前从它那里取出了std::future<>对象
  • 线程将会执行这个任务,该任务在内部调用相关的可调用实体,例如我们的函数getDataFromDB()。
  • 当这个函数给出返回值时,std::packaged_task<>将其设置为关联的共享状态,getDataFromDB()返回的结果或异常最终会在关联的未来对象中可用。
//获取packaged_task<>返回的结果,即getDataFromDB()返回的值。
std::string data = result.get();
  • get()函数将会阻塞调用线程,直到有可调用的实体返回,并且std::packaged_task<>将数据设置为其可共享的状态。
  • 完整的例子如下:
#include <iostream>
#include <thread>
#include <future>
#include <string>//从DB获取数据
std::string getDataFromDB(std::string token) {//获取数据std::string data = "Data fetched from DB by Filter :: " + token;return data;
}int main() {//创建封装回调函数的packaged_task<>std::packaged_task<std::string(std::string)> task(getDataFromDB);//从packaged_task<>获取相关的future<>std::future<std::string> result = task.get_future();//将packaged_task传递给线程以异步运行std::thread th(std::move(task), "Arg");//join线程,阻塞直到线程完成时返回th.join();//获取packaged_task<>的结果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0;
}
  • 输出:

Data fetched from DB by Filter :: Arg
  • 我们可以在同一行,用lambda函数或函数对象创建一个packaged_task
  • 使用lambda函数创建packaged_task
#include <iostream>
#include <thread>
#include <future>
#include <string>int main() {//创建封装了lambda函数的packaged_task<>std::packaged_task<std::string(std::string)> task([](std::string token) {std::string data = "Data From " + token;return data;});//从packaged_task<>获取相关的future<>std::future<std::string> result = task.get_future();//将packaged_task传递给线程以异步运行std::thread th(std::move(task), "Arg");//join线程,阻塞直到线程完成时返回th.join();//获取packaged_task<>的结果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0;
}
  • 输出:
Data fetched from DB by Filter :: Arg
  • 使用函数对象创建packaged_task
#include <iostream>
#include <thread>
#include <future>
#include <string>//从DB获取数据的函数对象
struct DBDataFetcher {std::string operator ()(std::string token) {std::string data = "Data From " + token;return data;}
};int main() {//使用函数对象创建packaged_taskstd::packaged_task<std::string(std::string)> task(std::move(DBDataFetcher()));//从packaged_task<>获取相关的future<>std::future<std::string> result = task.get_future();//将packaged_task传递给线程以异步运行std::thread th(std::move(task), "Arg");//join线程,阻塞直到线程完成时返回th.join();//获取packaged_task<>的结果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0;
}
  • 输出:

Data fetched from DB by Filter :: Arg

c++ packaged_task相关推荐

  1. C++11中std::packaged_task的使用

    C++11中的std::packaged_task是个模板类.std::packaged_task包装任何可调用目标(函数.lambda表达式.bind表达式.函数对象)以便它可以被异步调用.它的返回 ...

  2. C++并发编程之std::async(), std::future, std::promise, std::packaged_task

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...

  3. boost::packaged_task相关的测试程序

    boost::packaged_task相关的测试程序 实现功能 C++实现代码 实现功能 boost::packaged_task相关的测试程序 C++实现代码 #define BOOST_THRE ...

  4. std::future和std::promise和std::packaged_task

    std::future 其实future有两个兄弟,一个是std::future, 一个是它大哥std::shared_future.他们的区别就是std::future只支持移动语义,它所引用的共享 ...

  5. C++——异步操作(std::future、std::async、std::packaged_task、std::promise)

    文章目录 一.std::future与std::async 1.基本概念 2.代码演示 二.std::future与std::packaged_task 1.基本知识 2.代码演示 三.std::fu ...

  6. c++11多线程之packaged_task<>介绍与实例

    本节讨论c++11中std::packaged_task的特性与使用方法 std::packaged_task<> std::packaged_task<>是一个类模板,代表一 ...

  7. std::packaged_task() ---C++17 并发编程

    std::packaged_task() -C++17 并发编程 std::packaged_task<>连结了future对象与函数(或可调用对象). std::packaged_tas ...

  8. C++11 并发指南四(future 详解二 std::packaged_task 介绍)

    上一讲<C++11 并发指南四(<future> 详解一 std::promise 介绍)>主要介绍了 <future> 头文件中的 std::promise 类, ...

  9. C++ 中 async、packaged_task、promise 区别及使用

    Introduction 编程难,多线程编程更难 – 鲁迅 多线程编程,如此令人着迷.令人痛恨的字眼.人类为了追求更好的效率.更快的速度,非常残忍的发明了多线程编程,这不仅让写代码的难度陡增,同时也加 ...

  10. C++11多线程之 std::packaged_task

    简介 先给出官网的一个地址:http://www.cplusplus.com/reference/future/packaged_task/?kw=packaged_task 个人认为,相当于一个装饰 ...

最新文章

  1. C# 启动外部程序的几种方法
  2. MySQL count(1) count(*) 比较 详解
  3. Java与Cuda混合编程
  4. Android断点续传下载器JarvisDownloader
  5. Mysql运维管理-一主多从宕机从库切换主库继续和从库同步过程16
  6. ctags 的最简单使用
  7. 【图像分割】基于matlab超像素图像分割【含Matlab源码 720期】
  8. mate20pro换鸿蒙系统,鸿蒙2.0下载
  9. Linux系统软件看门狗
  10. 表白生成器PHP源码,表白网页在线生成源码
  11. 【Redis学习】:string数据类型详解
  12. 手绘vs码绘1——Q版小人
  13. python脚本实现GNSS数据自动下载
  14. 问题 B: 道路建设 (Ver. I)
  15. 基于水平集的图像分割方法
  16. echarts 折线图 设置y轴最小刻度_用plotly和plt画图的基本设置(标题、坐标轴、图例、注释、图像)...
  17. github提交代码命令(向开源社区提交代码)
  18. 如何使用 Unity制作微信小游戏,微信小游戏制作方案 最新完整详细教程来袭【持续更新】
  19. 二叉查找树——清华大学计算机系 郭家宝
  20. 基于ARM架构Cortex-A7 IMX6ULL 核心板设计核酸自动提取仪显控解决方案

热门文章

  1. 一种小微商户的调额方法值得您参考
  2. STM32F103ZE uIP DM9051 SPI以太网移植指南
  3. php 二维码在线识别api
  4. FMCW激光雷达科普(上):基本概念、技术路线、优势及争议和误解
  5. Django-(6)
  6. 互联网医疗仅剩的平台型超级独角兽,微医如何冲出重围?
  7. iReport与JasperReport中如何支持文支持显示
  8. android中涉及的字体修改
  9. 解决tomcat启动-Skipping unneeded JARs during scanning can improve startup time and JSP compilation time
  10. 男人为什么离不开酒?(写的太好了,句句入骨)