C++ std::future与promise(异步回调异步调用)
Posted Dontla
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ std::future与promise(异步回调异步调用)相关的知识,希望对你有一定的参考价值。
文章目录
std::future
std::future<Ret>
是一个C++标准库类,它表示一个异步操作的未来结果。它可以用来存储异步调用的结果。
案例1
// 下面是一个使用std::future<Ret> 的完整使用案例:
// 下面的代码使用std::packaged_task和std::future实现了异步回调函数AsyncCallback,其中Func为可调用对象,
// Arg为可调用对象f的参数列表,Ret为可调用对象f的返回类型。
// 首先,使用std::packaged_task封装可调用对象f,这样可以将一个普通函数转换为可调用对象,并且可以获取返回结果。
// 然后,使用std::future获取async函数的返回值,std::future是一个模板类,其模板参数Ret指定返回值的类型。
// 接着,将std::packaged_task实例task封装在std::thread中,并将参数arg传入线程中,当线程执行完毕之后,
// 通过future.get()获取返回结果,最后返回返回值。
// 为什么下面要用std::packaged_task而不用std::bind?
// 因为std::bind可以将一个普通函数或者可调用对象转换为可调用对象,但是它不能获取返回结果,而std::packaged_task则可以获取返回结果。
// 此外,std::packaged_task中的参数和返回类型都可以指定,而std::bind中的参数和返回类型无法指定。
#include <iostream> // 引入输入输出头文件
#include <future> // 引入future头文件
int add(int a, int b) // 定义求和函数
return a + b;
template <typename Func, typename Arg, typename Ret> // 定义泛型函数 //模板老编译不过不知道为什么。。。
Ret AsyncCallback(Func f, Arg arg) // 声明AsyncCallback函数
std::packaged_task<Ret(Arg)> task(f); // 创建一个std::packaged_task对象
std::future<Ret> future = task.get_future(); // 获取函数的返回值
std::thread t(std::move(task), arg); // 创建线程执行函数
t.join(); // 等待线程结束
return future.get(); // 返回函数的返回值
int main()
std::cout << "Result of add is: " << AsyncCallback<decltype(&add), int, int>(add, 5, 10) << std::endl; // 调用AsyncCallback函数
return 0;
编译运行:g++ test.cpp && ./a.out
编不过不知道为啥。。。
貌似模板没写对,改一下(不知为何在调用future.get()前必须显式join或detach子线程)
// 下面是一个使用std::future<Ret> 的完整使用案例
#include <iostream>
#include <future>
#include <chrono>
int add(int a, int b) // 定义求和函数
std::this_thread::sleep_for (std::chrono::seconds(2));
return a + b;
template <typename Ret, typename Func, typename ... Arg> // 定义泛型函数
Ret AsyncCallback(Func f, Arg ... arg)
std::packaged_task<Ret(Arg ...)> task(f); // 创建一个std::packaged_task对象
std::future<Ret> future = task.get_future(); // 获取函数的返回值
std::cout << "thread start" << std::endl;
std::thread t(std::move(task), arg ...); // 创建线程执行函数
t.join(); // 等待线程结束 //必须显示join或detach子线程,否则后面future.get就会报错,不知道什么原因
//t.detach();
//do something...
std::cout << "do something..." << std::endl;
std::this_thread::sleep_for (std::chrono::seconds(1));
return future.get();
int main()
int result = AsyncCallback<int>(add, 5, 10); // 调用AsyncCallback函数
std::cout << "Result of add is: " << result << std::endl;
return 0;
编译运行结果:
但是如果不join或detach:
不知道为什么非得显式join或detach,否则运行报错:terminate called without an active exception
貌似确实需要显式join或detach子线程,因为如果不那样做,线程对象在析构时将会检查线程对象状态,如果线程处于nonjoinable状态时,会调用terminate()函数直接令程序退出
参考文章:【C++】join()和detach|不join()也不detach()的后果
std::promise
std::future和std::promise结合使用
案例1
// linux C++使用Future和Promise实现一个线程对另一个线程的结果的传递和处理
#include <chrono>
#include <thread>
#include <future>
#include <iostream>
int compute(int x)
return x * x;
int main()
std::promise<int> result;
std::thread t([&result](int x)
int res = compute(x);
//result.set_value(res);
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "set_value start" << std::endl;
result.set_value(res*res); //只要本线程的promise执行set_value,另一个线程的future get就能立即得到
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "set_value end" << std::endl;
, 10); // pass 10 to the thread
std::cout << "get_future() start" << std::endl;
auto future = result.get_future(); //获取future对象
std::cout << "get() start" << std::endl;
int value = future.get(); //阻塞
std::cout << "Result is: " << value << '\\n';
t.join();
return 0;
编译运行结果:
C++什么情况下用future,什么情况下用promise,什么情况下两者都用,future和promise的的功能和作用是什么?
• Future:当我们想要获取一个异步运行的函数的结果时,可以使用Future。
• Promise:当我们想要将一个异步运行的函数的结果传递给另一个函数时,可以使用Promise。
• 两者都用:当我们想要需要一个线程实现对另一个线程的结果的传递和处理时,可以使用Future和Promise的结合来实现。
• Future的功能和作用:Future是一个异步运行的特殊类,它可以帮助我们在不阻塞程序流程的情况下,获取异步运行的函数的返回值。
• Promise的功能和作用:Promise是一个异步运行的特殊类,它可以帮助我们在不阻塞程序流程的情况下,将异步运行的函数的返回值传递到另一个函数中。
参考文章:c++11多线程编程同步——使用future和promise
以上是关于C++ std::future与promise(异步回调异步调用)的主要内容,如果未能解决你的问题,请参考以下文章
C++ std::future与promise(异步回调异步调用)
c++ 中的 std::promise 和 std::future
C++运行报错:what(): std::future_error: Broken promise