You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何等待任意C++异步任务执行完成并获取其原始启动索引

解决方案

你可以通过线程安全完成队列实现需求,该方案性能开销极低,不需要修改原有do_something的入参与返回值,也不需要每次任务完成时遍历整个future列表,完全符合你的要求。

步骤1:实现线程安全队列

如果对性能要求极高,可直接替换为工业级无锁队列,以下是基础的线程安全队列实现:

#include <queue>
#include <mutex>
#include <condition_variable>

template<typename T>
class ThreadSafeQueue {
private:
    std::queue<T> m_queue;
    std::mutex m_mutex;
    std::condition_variable m_cv;
public:
    void push(T value) {
        std::lock_guard<std::mutex> lock(m_mutex);
        m_queue.push(std::move(value));
        m_cv.notify_one();
    }

    T pop() {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_cv.wait(lock, [this] { return !m_queue.empty(); });
        T res = std::move(m_queue.front());
        m_queue.pop();
        return res;
    }
};

步骤2:修改业务代码

仅需要在提交异步任务时用lambda做一层轻量包装,捕获任务下标即可,不需要修改do_something的任何逻辑:

// 队列存储pair:第一个元素为任务启动的原始下标,第二个为do_something返回值
ThreadSafeQueue<std::pair<int, int>> comp_queue;
std::vector<std::future<void>> asyncs;

for (int i = 0; i < 4; ++i) {
    asyncs.push_back(std::async(
        std::launch::async,
        [i, &comp_queue] {
            int ret = do_something();
            comp_queue.push({i, ret});
        }
    ));
}

// 按任务完成顺序读取结果,每次操作为O(1),无遍历开销
for (int i = 0; i < 4; ++i) {
    auto [task_idx, wait_time] = comp_queue.pop();
    std::cout << "Task " << task_idx << " Wait time: " << wait_time << std::endl;
}

方案优势

  • 性能损耗极低:仅在任务完成和结果读取时各有一次队列操作,无锁队列实现下额外开销可忽略
  • 无需修改原有业务逻辑:do_something不需要接收索引参数,也不需要返回带索引的tuple
  • 天然支持按完成顺序输出结果,同时可获取任务的原始启动下标

内容的提问来源于stack exchange,提问作者CyanCoding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 05:36:04