我如何在 for 循环中等待所有生成的 JoinHandles

How do I await all spawned JoinHandles in a for loop

我有以下代码:

#[tokio::main]
async fn main() {
    let db: Db = Arc::new(Mutex::new(HashMap::new()));
    let block_res = get_block_addresses().await;

    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();

                tokio::spawn(async move {
                    let resp = check_if_contract(to, db1).await;
                });

                tokio::spawn(async move {
                    let resp = check_if_contract(from, db2).await;
                });
            }



        }
        Err(e) => {
            println!("error parsing header: {:?}", e);
        }
    }
}

如您所见,它从不等待生成结果。在 for 循环完成后,我如何正确等待这些 JoinHandles?我想避免使用一系列任务并迭代它们。因为我在 Jon Gjengset 的视频中看到存在类似 NotifyHandle 的东西,它按 ID 存储任务。但我不知道如何使用它,或者它在这种情况下是否有意义。我是生锈和异步编程的新手,所以我希望我的问题有一定道理。

此时对于动态数量的任务,最有效的方法是利用 FuturesUnordered,它代表 Future 的集合,可以在其中等待下一个 [=11] =] 解决。

在你的情况下,它应该是:

let tasks = FuturesUnordered::new();

for obj in v.result.transactions {
    let db1 = db.clone();
    let db2 = db.clone();

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

    tasks.push(tokio::spawn(async move {
        check_if_contract(to, db1).await
    }));

    tasks.push(tokio::spawn(async move {
        check_if_contract(from, db2).await
    }));
}

while let Some(finished_task) = tasks.next().await {
    match finished_task {
        Err(e) => { /* e is a JoinError - the task has panicked */},
        Ok(result) => { /* result is the result of check_if_contract */ }
    }
}

如果您需要在最终循环中识别事务,return 从您生成的函数中识别任务的东西 - 那么它将成为 result 的一部分。