C++异步调用 future async promise packaged_task

news/2024/10/14 18:41:34

背景:

C++ 异步调用是现代 C++ 编程中的一种重要技术,它允许程序在等待某个任务完成时继续执行其他代码,从而提高程序的效率和响应性。

C++11 引入了 std::async、std::future 和 std::promise 等工具,使得异步编程变得更加方便和直观。以下是关于 C++ 异步调用的详细介绍,包括基本概念、使用方法和示例代码。

以下代码头文件为:

#include <iostream>
#include <future>
#include <thread>
#include <chrono>

std::future:

std::future 是一个类模板,提供了一种访问异步操作结果的机制。

主要成员函数包括 get、wait 和 wait_for,其中 get 用于获取异步操作的结果,如果结果还不可用,get 会阻塞当前线程,直到结果可用。

注意

不能单独使用一定配合另外三个使用

get只能调用一次多次调用抛异常

调用wait(仍然可以使用get()获取结果

wait_for()等待异步操作完成等待指定时间段如果超时返回timeout.

 

std::async:

std::async 是一个函数模板,用于启动异步任务。它返回一个 std::future 对象,可以用来获取异步任务的结果。

std::async 可以指定执行策略。例如 std::launch::async 表示在新线程中异步执行std::launch::deferred 表示延迟执行,直到调用 std::future::get 或 std::future::wait 时才开始执行

 代码:

int compute(int x) 
{std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作return x * x;
}int asyncTest()
{// 启动异步任务std::future<int> result = std::async(std::launch::async, compute, 5);// 继续执行其他代码std::cout << "Doing some other work..." << std::endl;// 获取异步任务的结果int value = result.get(); // 这里会等待。std::cout << "Result: " << value << std::endl;return 0;
}

 

std::promise:

std::promise 是一个类模板,用于在异步任务中设置结果值。std::promise 可以与 std::future 配合使用,通过 std::promise::set_value 设置结果值,然后通过 std::future::get 获取结果值。

如何理解配合thread用来获取另外一个线程的执行结果

如图1)启动线程B时可以传一个菜篮子(就是promise)进去。2)当线程B干完可以菜篮子。3)线程A通过get获取菜篮子

注意事项

1.  std::promise的生命周期:确保std::promise对象在std:: future对象需要它之前保持有效。一旦std::promise对象被销毁,任何尝试通过std:: future对象访问其结果的操作都将失败。

2.  线程安全:std::promise的set_value和set_exception方法是线程安全的,但你应该避免在多个线程中同时调用它们,因为这通常意味着你的设计存在问题。

3.  异常处理:当使用std::promise时,要特别注意异常处理。如果std::promise的set_exception方法没有被调用,但异步操作中确实发生了异常,那么这些异常将不会被捕获,并可能导致程序崩溃。

4.  性能考虑:虽然std::promise和std::future提供了强大的异步编程能力,但它们也引入了额外的开销。在性能敏感的应用程序中,要仔细考虑是否真的需要它们。

5.  std::move 的使用:在将std::promise对象传递给线程函数时,通常需要使用std::move来避免不必要的复制。这是因为std::promise对象通常包含非托管资源(如共享状态),复制它们可能是昂贵的或不必要的。

 代码:

void doWork(std::promise<int>&& p) {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作p.set_value(42); // 设置结果值
}int promiseTest() 
{std::promise<int> prom;  // 创建 promisestd::future<int> fut = prom.get_future();// 启动线程执行异步任务.  注意这里一定要用move进去,不能用拷贝构造。
    std::thread t(doWork, std::move(prom));// 继续执行其他代码std::cout << "Doing some other work..." << std::endl;// 获取异步任务的结果int value = fut.get();std::cout << "Result: " << value << std::endl;t.join();return 0;
}

 

std::packaged_task:

std::packaged_task 是一个类模板,包装了一个可调用对象(如普通函数、lambda 表达式、函数对象等),以便异步调用。它也可以与 std::future 配合使用,通过 std::packaged_task::get_future 获取 std::future 对象。

就是一堆函数封装一下方便异步调用适合用来线程池不同任务封装成统一packaged_task然后统一调度参考https://www.cnblogs.com/xcywt/p/18429228

启动流程

 代码:

int computeTTT(int x) 
{std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作return x * x;
}int packaged_task_Test() {// 创建 packaged_taskstd::packaged_task<int(int)> task(computeTTT);  // 把一个函数包装一下。std::future<int> result = task.get_future();// 启动线程执行异步任务std::thread t(std::move(task), 5);// 继续执行其他代码std::cout << "Doing some other work..." << std::endl;// 获取异步任务的结果int value = result.get();std::cout << "Result: " << value << std::endl;t.join();return 0;
}

 

比较:

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/71549.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

WPF - 项目样例

WPF - 项目样例1. 创建项目: 参考:https://www.cnblogs.com/1285026182YUAN/p/184623962. 修改App.xaml<Application x:Class="ModelFileMigrate.App"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schema…

Spring 实现 3 种异步流式接口,干掉接口超时烦恼

大家好,我是小富~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地向客户端响应处…

世界空间到观察空间的矩阵

1)世界空间到观察空间的矩阵2)Addressable在不同工程中如何实现打包和加载3)如何设计角色在下蹲时允许跳跃4)如何实时编辑玩家的近裁剪面距离这是第403篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和学习…

rocketMQ中事务发送消息

rocketMQ中有关事务的发送消息方式,写的一个demo 1、在MyProducer类中的方法,即先定义调用@Component public class MyProducer {@Autowiredprivate RocketMQTemplate template; public void sendTractionMessage(String topic, String msg) throws InterruptedException {St…

为什么线下面试越来越流行了?

不知道大家有没有发现,最近在找工作时,越来越多的公司开始要求必须线下面试了,例如,深信服:例如,华为:还有公司在发布招聘信息时也明确写明了“只能线下面试”:那背后的原因究竟是啥呢? 原因一:作弊成本越来越低 AI 的诞生确实提供了很多便利,但也有人和团队利用 AI…

罗技键鼠在使用Synergy中的灵敏度问题

罗技键鼠在使用Synergy中的灵敏度问题 设备清单mac电脑一台(作为主控端) windows电脑一台(作为被控端) logi master系列键鼠一套遇到的问题 Synergu已经正常启用。mac作为主控设备,且关闭了logi flow情况下,在windows(被控端)使用鼠标明显慢很多,原因是罗技鼠标在mac上…

HDLBits 练习题:8位移位寄存器

HDLBits 练习题:8 位移位寄存器 原题 This exercise is an extension of module_shift. Instead of module ports being only single pins, we now have modules with vectors as ports, to which you will attach wire vectors instead of plain wires. Like everywhere else…

IntelliJ IDEA 2024激活码(亲测有效,仅供学习和交流)

资源是从官网购买,仅供学习和交流 激活码链接地址