在C++的异步编程体系中,std::promise用于在一个线程中设置异步操作的结果,std::future则用于在另一个线程中获取这个结果,二者配合可以实现跨线程的结果传递。要实现异步任务的链式调用,核心思路就是让前一个任务的结果作为后一个任务的输入,通过promise和future的衔接完成整个调用链。

核心组件基础概念
首先我们需要明确两个核心组件的基本用法:
- std::promise:是一个承诺对象,我们可以在异步线程中调用它的set_value方法设置结果,也可以调用set_exception设置异常。
- std::future:是未来对象,通过promise的get_future方法获取,调用它的get方法可以阻塞等待promise设置结果,获取之后才能继续执行后续逻辑。
链式调用的实现思路
任务链式调用的本质是前一个任务完成后,自动触发下一个任务的执行,并且前一个任务的结果要传递给下一个任务。我们可以通过封装任务执行逻辑,让每个任务内部持有下一个任务的promise,当前任务完成后将结果设置到下一个任务的promise中,从而触发下一个任务的future等待结束,执行后续逻辑。
基础链式调用实现
我们先实现一个简单的两个任务链式调用,第一个任务执行完成后,结果传递给第二个任务执行:
#include <iostream>
#include <future>
#include <thread>
#include <functional>
// 第一个异步任务,接收输入参数,返回计算结果
int task1(int input) {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作
return input * 2;
}
// 第二个异步任务,接收第一个任务的结果,返回最终计算结果
int task2(int input) {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟耗时操作
return input + 10;
}
int main() {
// 创建第一个任务的promise和future
std::promise<int> promise1;
std::future<int> future1 = promise1.get_future();
// 启动第一个任务的线程
std::thread t1([&promise1]() {
int result = task1(5); // 执行第一个任务,输入参数为5
promise1.set_value(result); // 将结果设置到promise1中
});
// 创建第二个任务的promise和future
std::promise<int> promise2;
std::future<int> future2 = promise2.get_future();
// 启动第二个任务的线程,等待第一个任务的结果
std::thread t2([&promise2, &future1]() {
int pre_result = future1.get(); // 阻塞等待第一个任务的结果
int result = task2(pre_result); // 用第一个任务的结果执行第二个任务
promise2.set_value(result); // 将第二个任务的结果设置到promise2中
});
// 获取最终链式调用的结果
int final_result = future2.get();
std::cout << "链式调用最终结果: " << final_result << std::endl;
t1.join();
t2.join();
return 0;
}
通用链式调用封装
上面的实现只能固定两个任务,我们可以封装一个通用的链式调用工具,支持任意多个任务按顺序执行:
#include <iostream>
#include <future>
#include <thread>
#include <vector>
#include <functional>
#include <memory>
// 链式调用管理器
class AsyncTaskChain {
public:
// 添加任务到链中,任务类型为接收上一个结果返回新结果的函数
template <typename Func>
void then(Func&& func) {
tasks.emplace_back(std::forward<Func>(func));
}
// 启动链式调用,传入初始参数
template <typename T>
std::future<T> execute(T init_val) {
// 创建最终结果的promise
auto final_promise = std::make_shared<std::promise<T>>();
std::future<T> final_future = final_promise->get_future();
// 如果没有任务,直接返回初始值
if (tasks.empty()) {
final_promise->set_value(init_val);
return final_future;
}
// 反向遍历任务,从最后一个任务开始创建promise和future链
std::shared_ptr<std::promise<T>> prev_promise = final_promise;
for (int i = tasks.size() - 1; i >= 0; --i) {
auto current_promise = std::make_shared<std::promise<T>>();
std::future<T> current_future = current_promise->get_future();
auto task_func = tasks[i];
// 启动线程执行当前任务,等待上一个任务的结果
std::thread([current_promise, prev_promise, task_func, current_future]() mutable {
// 如果是最后一个任务,等待初始值或者前一个任务的结果
T input;
if (prev_promise->get_future().valid()) {
input = prev_promise->get_future().get();
}
T result = task_func(input);
current_promise->set_value(result);
}).detach();
prev_promise = current_promise;
}
// 设置初始值到第一个任务的promise
prev_promise->set_value(init_val);
return final_future;
}
private:
std::vector<std::function<int(int)>> tasks; // 任务列表,这里简化为统一接收int返回int
};
// 示例任务函数
int add_ten(int val) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
return val + 10;
}
int multiply_two(int val) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
return val * 2;
}
int subtract_five(int val) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
return val - 5;
}
int main() {
AsyncTaskChain chain;
// 添加三个任务到链中
chain.then(add_ten);
chain.then(multiply_two);
chain.then(subtract_five);
// 执行链式调用,初始值为3
std::future<int> result_future = chain.execute(3);
int final_result = result_future.get();
std::cout << "通用链式调用最终结果: " << final_result << std::endl;
// 执行逻辑:3+10=13,13*2=26,26-5=21,最终输出21
return 0;
}
注意事项
- 使用std::future的get方法时,只能调用一次,多次调用会导致未定义行为,如果需要多次获取结果,可以改用std::shared_future。
- 如果promise在销毁前没有设置值,调用future的get方法会抛出std::future_error异常,所以需要确保每个promise都有对应的结果设置逻辑。
- 链式调用中如果某个任务抛出异常,需要在promise中调用set_exception方法设置异常,否则后续任务会一直阻塞等待结果。
- 线程的创建和销毁有一定开销,如果任务链较长,可以考虑使用线程池来优化性能,避免频繁创建线程。
总结
通过std::future和std::promise的配合,我们可以实现灵活的异步任务链式调用逻辑,核心是利用promise设置结果、future等待结果的机制,将多个异步任务的结果传递串联起来。上述通用封装可以满足大部分简单的链式调用需求,实际开发中可以根据业务场景调整任务函数的参数和返回值类型,适配更复杂的业务逻辑。
C++std::futurestd::promise异步任务任务链式调用修改时间:2026-07-19 13:48:39