You need to enable JavaScript to run this app. Rust Tokio中如何在for循环结束后等待所有已spawn的JoinHandle完成
优惠活动
大模型
产品
解决方案
定价
更多

Rust Tokio中如何在for循环结束后等待所有已spawn的JoinHandle完成

解决方案

你提到的工具大概率是Tokio内置的JoinSet(你可能记错了名称),它专门用于批量管理异步任务,不需要你手动维护任务数组来遍历等待,完全适配当前场景。

改造后的代码

use std::sync::{Arc, Mutex};
use std::collections::HashMap;
use tokio::task::JoinSet;

// 假设你已经定义了Db类型、get_block_addresses、check_if_contract方法
type Db = Arc<Mutex<HashMap<String, bool>>>;

#[tokio::main]
async fn main() {
    let db: Db = Arc::new(Mutex::new(HashMap::new()));
    let block_res = get_block_addresses().await;
    // 初始化任务集合,自动管理所有 spawn 的异步任务
    let mut task_set = JoinSet::new();

    match block_res {
        Ok(v) => {
            println!("Block downloaded, grabbing contracts");
            println!("Txs: {}", v.result.transactions.len());
            for obj in v.result.transactions {
                let db1 = db.clone();
                let db2 = db.clone();

                let to = obj.to.clone();
                let from = obj.from.clone();

                // 把任务加入集合,不需要手动保存句柄
                task_set.spawn(async move {
                    let resp = check_if_contract(to, db1).await;
                    // 如果需要关联地址和结果,可直接在这里返回元组:(to, resp)
                    resp
                });

                task_set.spawn(async move {
                    let resp = check_if_contract(from, db2).await;
                    // 同理可返回 (from, resp)
                    resp
                });
            }

            // 等待所有任务执行完毕
            while let Some(res) = task_set.join_next().await {
                match res {
                    Ok(task_result) => {
                        // 在这里处理单个任务的返回结果
                    }
                    Err(join_err) => {
                        // 处理任务执行失败的情况,比如任务panic
                        eprintln!("任务执行出错: {:?}", join_err);
                    }
                }
            }
        },
        Err(e) => {
            println!("error parsing header: {:?}", e);
        }
    }
}

核心逻辑说明

  • JoinSet内部自动维护了所有提交任务的JoinHandle,你不需要手动创建Vec<JoinHandle>来存储
  • 如果你需要按ID关联任务和结果:task_set.spawn会返回唯一的TaskId,你可以在提交任务时把TaskId和对应的地址(to/from)存入你的DB映射表,后续join_next返回结果时会附带对应的TaskId,直接匹配即可
  • 如果你不需要处理每个任务的返回值,只需要等待所有任务执行完成,也可以直接调用task_set.join_all().await,不需要写循环处理每个结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 07:15:09