C++ 异步编程:std::async、std::future、std::packaged_task 和 std::promise
C++ 异步编程:std::async、std::future、std::packaged_task 和 std::promise
在现代 C++ 编程中,异步编程已经成为一种常见的模式。利用 C++11 引入的标准库组件 std::async、std::future、std::packaged_task 和 std::promise,我们可以更方便地处理多线程任务。本文将介绍这些组件的基本用法及其应用场景,帮助你理解如何利用这些工具实现高效的异步编程。
1. std::future 和 std::promise
std::future
std::future 是一种用于获取异步计算结果的机制。它提供了一个等待异步任务完成并获取结果的方法。std::future 对象通过与 std::promise 结合使用,允许线程安全地获取异步操作的结果或异常。
基本用法:
#include <iostream>
#include <thread>
#include <future>void async_task(std::promise<int>& prom) {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作prom.set_value(42); // 设置计算结果
}int main() {std::promise<int> prom;std::future<int> fut = prom.get_future();std::thread t(async_task, std::ref(prom)); // 使用 std::ref 传递 promise 的引用t.detach(); // 线程分离,允许在主线程中继续执行int result = fut.get(); // 等待异步任务完成并获取结果std::cout << "Result: " << result << std::endl;return 0;
}
解释:
std::promise<int>创建一个promise对象,用于设置值。std::future<int> fut = prom.get_future();从promise获取future对象。- 在异步线程中,调用
prom.set_value(42);设置结果。 fut.get();阻塞当前线程,直到结果可用。
std::promise
std::promise 用于在异步操作中设置结果。它与 std::future 结合使用,以便从线程中传递结果或异常。std::promise 对象只能被设置一次,设置多次会引发异常。
基本用法:
#include <iostream>
#include <thread>
#include <future>void async_task(std::promise<int> prom) {prom.set_value(42); // 设置计算结果
}int main() {std::promise<int> prom;std::future<int> fut = prom.get_future();std::thread t(async_task, std::move(prom)); // 使用 std::move 转移 promiset.join(); // 等待线程完成int result = fut.get(); // 获取异步任务的结果(会阻塞直到结果可用)std::cout << "Result: " << result << std::endl;return 0;
}
解释:
std::promise<int> prom;创建promise对象。std::future<int> fut = prom.get_future();获取future对象。- 在异步线程中,通过
prom.set_value(42);设置结果。 fut.get();获取结果并阻塞当前线程。
2. std::packaged_task
std::packaged_task 是一个可调用对象,用于将任务的结果与 std::future 绑定。它允许你将一个普通的函数或函数对象封装为一个异步任务,并从中获取结果。
基本用法:
#include <iostream>
#include <thread>
#include <future>int long_computation(int x) {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作return x * x;
}int main() {std::packaged_task<int(int)> task(long_computation); // 创建任务std::future<int> fut = task.get_future(); // 获取 future 对象std::thread t(std::move(task), 10); // 使用 std::move 转移任务,并传递参数t.join(); // 等待线程完成int result = fut.get(); // 获取异步任务的结果(会阻塞直到结果可用)std::cout << "Result: " << result << std::endl;return 0;
}
解释:
std::packaged_task<int(int)> task(long_computation);创建一个任务对象,封装long_computation函数。std::future<int> fut = task.get_future();获取与任务关联的future对象。std::thread t(std::move(task), 10);将任务移动到线程中,并传递参数。fut.get();获取任务结果。
3. std::async
std::async 是一种更高层次的异步操作工具,它可以在后台线程中异步执行函数,并返回一个 std::future 对象,用于获取结果。它比手动创建线程更简单。
基本用法:
#include <iostream>
#include <future>
#include <chrono>int long_computation(int x) {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作return x * x;
}int main() {std::future<int> fut = std::async(std::launch::async, long_computation, 10); // 异步执行// 可以在这里做其他事情std::cout << "Doing other things while waiting for the result..." << std::endl;int result = fut.get(); // 获取异步任务的结果(会阻塞直到结果可用)std::cout << "Result: " << result << std::endl;return 0;
}
解释:
std::async(std::launch::async, long_computation, 10);异步执行long_computation函数,并传递参数。fut.get();获取结果并阻塞当前线程,直到结果可用。
总结
std::promise用于设置异步操作的结果或异常。std::future用于获取异步操作的结果或异常。std::packaged_task封装函数为任务,并与std::future结合使用。std::async简化异步任务的创建和管理,自动处理线程和任务。
通过理解和使用这些 C++ 标准库组件,你可以更高效地进行异步编程,管理复杂的任务和线程操作。
相关文章:
C++ 异步编程:std::async、std::future、std::packaged_task 和 std::promise
C 异步编程:std::async、std::future、std::packaged_task 和 std::promise 在现代 C 编程中,异步编程已经成为一种常见的模式。利用 C11 引入的标准库组件 std::async、std::future、std::packaged_task 和 std::promise,我们可以更方便地处…...
OD C卷 - 石头剪刀布游戏
石头剪刀布游戏 (100) 剪刀石头布游戏,A-石头、B-剪刀、C-布游戏规则: 胜负规则,A>B; B>C; C>A;当本场次中有且仅有一种出拳形状优于其他出拳形状,则该形状的玩家是胜利者,否则认为是…...
关于k8s集群中kubectl的陈述式资源管理
1、k8s集群资源管理方式分类 (1)陈述式资源管理方式:增删查比较方便,但是改非常不方便 使用一条kubectl命令和参数选项来实现资源对象管理操作 (2)声明式资源管理方式:yaml文件管理 使用yam…...
XML 学习笔记
简介: (1)XML:可扩展性标记语言,用于传输和存储数据,而不是展示数据,是W3C 推举的数据传输格式。 XML的标签必须自定义,但是在写标签名的时候一定要有含义。 XML 只能有一个根节点…...
MongoDB未授权访问漏洞
2.MongoDB未授权访问漏洞 mongodb数据库是由C编写,主要是为了提供web应可用扩展的一种高性能数据库。开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作(增、删、改、查高危动作)而且可以远程访问数据库…...
数据安全、信息安全、网络安全区别与联系
关键字: 信息安全 数据安全 网络安全 [导读] 让人更好理解 “数据安全”、“信息安全”、“网络安全” 三者间的区别与联系了,我们汇总了官方机构给这三者的定义,并且网友也给出了自己的看法,一起来看看。 在 “互联网 ” 被广…...
Jenkins未授权访问漏洞 *
漏洞复现 步骤一:使用以下fofa语法进行产品搜索.... port"8080" && app"JENKINS" && title"Dashboard [Jenkins]" 步骤二:在打开的URL中...点击Manage Jenkins --> Scritp Console在执行以下命令..…...
【爬虫原理】
《爬虫》 1、爬虫的概念 概念:(spider,网络蜘蛛)通过互联网上一个个的网络节点,进行数据的提取、整合以及存储 分类: 通用爬虫(了解) 主要用于搜索引擎(百度、…...
计算机组成原理 —— 指令流水线的基本概念
计算机组成原理 —— 指令流水线的基本概念 串行执行(Serial Execution)串行执行的特点串行执行的局限性串行执行的应用场景 并行执行定义基本原理五段式指令流水线优点缺点 流水线的性能指标示例计算 我们来了解一下指令流水线: 首先在这之…...
Python爬虫技术 第31节 持续集成和自动化部署
持续集成和自动化部署 Git版本控制 Git 是一个非常流行的分布式版本控制系统,用于跟踪对项目文件的修改。对于爬虫项目来说,使用Git可以帮助你管理代码的不同版本,协同开发,并且可以在出现问题时回滚到之前的版本。 基本操作&a…...
数据结构(C语言版)(第2版)课后习题答案
数据结构(C语言版)(第2版)课后习题答案 李冬梅 2015.3 目 录 第 1 章 绪论 1 第 2 章 线性表 5 第 3 章 栈和队列 13 第 4 章 串、数组和广义表 26 第 5 章 树和二叉树 33 第 6 章 图 43 第 7 章 查找 54 第 8 章 排序 65…...
打开轮盘锁问题(LeetCode)的分析总结及进一步提问
打开轮盘锁问题分析总结,及进一步提问:请给出一组最小步数下的号码序列组合 题目描述 你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由…...
python——joblib进行缓存记忆化-对计算结果缓存
问题场景 在前端多选框需要选取多个数据进行后端计算。 传入后端是多个数据包的对应路径。 这些数据包需要按一定顺序运行,通过一个Bag(path).get_start_time() 可以获得一个float时间值进行排序,但由于数据包的特性,这一操作很占用性能和时…...
Linux文件管理
系列文章目录 提示:仅用于个人学习,进行查漏补缺。 1.Linux介绍、目录结构、文件基本属性、Shell 2.Linux常用命令 3.Linux文件管理 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1…...
《Unity3D网络游戏实战》学习与实践--制作一款大乱斗游戏
角色类 基类Base Human是基础的角色类,它处理“操控角色”和“同步角色”的一些共有功能;CtrlHuman类代表“操控角色”,它在BaseHuman类的基础上处理鼠标操控功能;SyncHuman类是“同步角色”类,它也继承自BaseHuman&…...
文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑源-荷不确定性的省间电力现货市场潮流风险概率评估》
本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…...
Pinterest 选择采用 TiDB
原文来源: https://tidb.net/blog/9f000c95 作者:Pinterest 公司高级软件工程师 Alberto Ordonez Pereira ;高级工程经理 Lianghong Xu 声明:本文转载于 https://medium.com/pinterest-engineering/tidb-adoption-…...
【Python】 如何用 Docker 打包一个 Python 脚本
这是我父亲 日记里的文字 这是他的生命 留下留下来的散文诗 几十年后 我看着泪流不止 可我的父亲已经 老得像一个影子 🎵 许飞《父亲写的散文诗》 如何用 Docker 打包一个 Python 脚本 Docker 是一个开源的容器化平台,允许开发者将…...
从“幕后”到“台前”:一文读懂API经济如何促进企业的创新与增长
API(Application Programming Interface,应用程序接口)指一组定义软件程序如何与其他组件、服务或系统交互的规范。在传统的IT语境中,API往往更多承担前后端对接或应用系统间内部集成渠道的作用。但在当今大数据与智能化的时代&am…...
解锁PDF新姿势:2024年PDF转图片工具精选
随着数字化办公的普及和文档处理需求的日益增长,PDF转图片工具已成为日常工作中不可或缺的一部分。这些工具不仅帮助用户轻松地将PDF文件转换为图片格式,还提供了丰富的编辑、转换和批量处理功能,极大地提高了工作效率。 1.福昕PDF转换大师&…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
门静脉高压——表现
一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构:由肠系膜上静脉和脾静脉汇合构成,是肝脏血液供应的主要来源。淤血后果:门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血,引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...
【QT控件】显示类控件
目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏:QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…...
