如何让C++异步调用按完成顺序返回结果?
按异步任务完成顺序获取结果的C++实现
你的原代码通过std::async启动异步任务,但遍历std::future时按调用顺序调用get(),因此输出顺序固定为任务启动顺序。要实现按任务完成顺序输出结果,std::experimental::when_any是可行方案——尽管它属于实验特性,但主流编译器(GCC、Clang、MSVC)在开启对应选项后均支持使用。
修改后的示例代码
#include <iostream> #include <future> #include <chrono> #include <thread> #include <utility> #include <string> #include <vector> #include <experimental/future> // 引入when_any头文件 std::pair<int, std::string> check_even(int num){ std::this_thread::sleep_for(std::chrono::milliseconds((10 - num) * 100)); if(num % 2 == 0) return {num, "even"}; return {num, "odd"}; } int main(){ std::vector<std::future<std::pair<int, std::string>>> futures; for(int i = 0; i < 10; i++){ futures.push_back(std::async(std::launch::async, check_even, i)); // 显式指定std::launch::async确保任务异步执行(默认策略可能选择同步) } while(!futures.empty()){ // 调用when_any获取第一个完成的任务 auto result = std::experimental::when_any(futures.begin(), futures.end()); // 获取已完成任务的索引 size_t completed_idx = result.index; // 获取任务结果 auto rs = futures[completed_idx].get(); std::cout << rs.first << " is " << rs.second << '\n'; // 移除已处理的future,继续等待剩余任务 futures.erase(futures.begin() + completed_idx); } return 0; }
关键说明
- 头文件依赖:需要引入
<experimental/future>来使用std::experimental::when_any。 - 显式异步策略:原代码中
std::async默认策略可能选择同步执行,因此显式指定std::launch::async确保任务在独立线程中运行。 - when_any的作用:
when_any接受一个std::future的范围,返回一个包含以下信息的结构体:index:第一个完成任务在原容器中的索引futures:原容器的副本(其中已完成的future处于ready状态)
- 编译选项:使用GCC编译时需添加参数
-std=c++17 -lstdc++experimental,Clang类似,MSVC可直接启用C++17及以上标准编译。
预期输出
由于任务的休眠时间随num增大而缩短,任务完成顺序为9→8→7→…→0,输出如下:
9 is odd 8 is even 7 is odd 6 is even 5 is odd 4 is even 3 is odd 2 is even 1 is odd 0 is even
内容的提问来源于stack exchange,提问作者Caio
相关产品推荐
相关产品推荐

