0

0

c++怎么使用std::async执行异步任务_c++ 未来对象std::future结果获取【教程】

尼克

尼克

发布时间:2025-12-27 07:01:34

|

948人浏览过

|

来源于php中文网

原创

std::async默认策略不保证真异步,需显式指定std::launch::async;std::future::get()仅能调用一次且阻塞,未调用则析构时隐式wait;不支持多消费者,须用std::shared_future或std::move转移所有权;异常在get()时重抛。

c++怎么使用std::async执行异步任务_c++ 未来对象std::future结果获取【教程】

std::async 启动异步任务时,launch策略决定是否真异步

默认情况下 std::async 不一定真正并发执行——它可能延迟到 get()wait() 时才同步运行(std::launch::deferred 策略)。这常导致“以为异步,实则卡主线程”的问题。

  • 显式指定 std::launch::async 强制新开线程:
    auto fut = std::async(std::launch::async, []{ return 42; });
  • 不指定策略时,编译器可自由选择;MSVC 默认倾向 deferred,GCC/Clang 多数情况走 async,但不可依赖
  • 混合使用两种策略时,注意资源竞争:多个 std::launch::async 任务共享线程池(标准未规定池大小,实际由实现决定)

std::future::get() 只能调用一次,且会阻塞等待完成

get() 是获取结果的唯一合法方式,但它有强副作用:首次调用后,该 std::future 对象进入无效状态,再次调用会抛出 std::future_error(错误码为 std::future_errc::no_state)。

  • 调用前可用 valid() 检查是否还持有有效状态:
    if (fut.valid()) { auto res = fut.get(); }
  • 若只需等待完成、不关心返回值,用 wait() 更安全
  • 在析构前未调用 get()wait(),会导致析构时隐式调用 wait() —— 这可能让你在意外位置被阻塞

std::future 不支持多消费者,也不能跨线程转移所有权

std::future 是独占所有权类型,移动后原对象失效,且不能拷贝。这意味着它无法像 std::shared_future 那样被多个线程同时等待或取值。

  • 需要共享结果时,改用 std::shared_future
    auto fut = std::async([]{ return "done"; }); auto sf = fut.share();
  • 想把 future 传给另一个线程处理?必须用 std::move
    std::thread t([f = std::move(fut)]{ f.get(); });
  • lambda 捕获 future 时也需显式移动:
    [fut = std::move(fut)]() mutable { fut.get(); }

异常传播:异步函数抛异常,get() 会重新抛出

如果 async 中的函数抛出异常,std::future::get() 不会返回值,而是直接重抛该异常(类型不变)。这是 std::future 的核心设计之一,但容易忽略其传播时机。

Dreamphilic
Dreamphilic

一个基于web的工具,为用户提供AI生成的内容。

下载

立即学习C++免费学习笔记(深入)”;

  • 异常只在第一次 get() 时抛出;后续调用仍报 no_state
  • 若异步任务已抛异常但你只调用了 wait(),异常不会触发,直到你调用 get()
  • 建议始终用 try/catch 包裹 get(),尤其在封装异步调用时:
    try { auto res = fut.get(); } catch (const std::exception& e) { /* 处理 */ }

真正麻烦的是:一旦 std::future 被 move 出作用域,又没在析构前 get()wait(),程序就可能卡死在析构点——这个行为静默且难以调试。

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

201

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

187

2025.11.08

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

465

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

465

2023.08.10

虚拟号码教程汇总
虚拟号码教程汇总

本专题整合了虚拟号码接收验证码相关教程,阅读下面的文章了解更多详细操作。

30

2025.12.25

错误代码dns_probe_possible
错误代码dns_probe_possible

本专题整合了电脑无法打开网页显示错误代码dns_probe_possible解决方法,阅读专题下面的文章了解更多处理方案。

20

2025.12.25

网页undefined啥意思
网页undefined啥意思

本专题整合了undefined相关内容,阅读下面的文章了解更多详细内容。后续继续更新。

37

2025.12.25

word转换成ppt教程大全
word转换成ppt教程大全

本专题整合了word转换成ppt教程,阅读专题下面的文章了解更多详细操作。

6

2025.12.25

msvcp140.dll丢失相关教程
msvcp140.dll丢失相关教程

本专题整合了msvcp140.dll丢失相关解决方法,阅读专题下面的文章了解更多详细操作。

2

2025.12.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号