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
相关产品推荐
相关产品推荐

