提问人:Mike Altonji 提问时间:11/9/2023 更新时间:11/9/2023 访问量:72
'tokio::try_join!' 在 'JoinHandle 的向量上
`tokio::try_join!` on a vector of `JoinHandle`s
问:
Rust 新手。我想等待以下异步任务完成:
let _ = tokio::try_join!(fetch_handle, evaluate_handles[0], evaluate_handles[1], evaluate_handles[2], evaluate_handles[3]);
有没有办法在不对每个项目进行硬编码的情况下做到这一点? 是一个 ,并且只是一个evaluate_handles
evaluate_handles
Vec<JoinHandle<()>>
fetch_handle
JoinHandle<()>
答:
为此,你可以将所有 s 放入 FuturesUnordered
中,然后将其作为 :JoinHandle
Stream
use std::time::Duration;
use futures::{stream::FuturesUnordered, StreamExt};
#[tokio::main]
async fn main() {
let tasks = FuturesUnordered::new();
for i in 0..10 {
tasks.push(tokio::spawn(async move {
println!("task {i} starting");
tokio::time::sleep(Duration::from_secs(1)).await;
println!("task {i} finished");
}));
}
println!("joining tasks");
tasks.for_each(|_| async {}).await;
println!("joined all tasks");
}
(操场)
请注意,你可以进入一个,所以如果你能将任务表达为迭代器,你可以使代码变得简单得多。collect
FuturesUnordered
JoinHandles
use std::time::Duration;
use futures::{stream::FuturesUnordered, StreamExt};
#[tokio::main]
async fn main() {
let tasks: FuturesUnordered<_> = (0..10)
.map(|i| {
tokio::spawn(async move {
println!("task {i} starting");
tokio::time::sleep(Duration::from_secs(1)).await;
println!("task {i} finished");
})
})
.collect();
println!("joining tasks");
tasks.for_each(|_| async {}).await;
println!("joined all tasks");
}
(操场)
评论
try_join
FuturesUnordered
FuturesUnordered
JoinHandle
Err
try_for_each
for_each
FuturesUnordered
try_for_each
对我来说并不明显(可以实现 TryStream
的事实也让我感到惊讶)。像这样的例子可能已经解释了更好的灵活性。FuturesUnordered
while let Some(completed) = tasks.next().await { /* handle task results in order of completion */ }
FuturesUnordered
Result
warning: unused Result that must be used
Result
一般来说,你可以用在任务(futures)的迭代器上做:TryJoinAll
try_join!
use futures::future::TryJoinAll;
let join_evaluate_handles = evaluate_handles.into_iter().collect::<TryJoinAll<_>>();
在您的例子中,所有连接句柄都具有相同的类型,因此您可以构造一个包含所有句柄的迭代器:
evaluate_handles.into_iter()
.chain(once(fetch_handle))
.collect::<TryJoinAll<_>>()
.await
如果它们不是同一类型,则将组合和:TryJoinAll
try_join!
try_join!(fetch_handle, join_evaluate_handles /* from above */)
但是请注意,我不确定在这里使用它是否非常有意义。的要点是,如果其中一个期货错误,它会立即返回。但是你的未来是 s,只有当生成的任务崩溃时才会出错:Playground Now,在生成的未来中恐慌会使 tokio 打印出一条丑陋的错误消息,你通常希望避免这种情况。我能想到的唯一实际用例是,如果某处发生恐慌,请中止您的应用程序。但我认为没有那么多麻烦的方法可以做到这一点。try_join
try_join
JoinHandle
try_join
还有一点需要注意:如果您使用的是 或 ,则一开始就不需要您的任务。TryJoinAll
FuturesUnordered
tokio::spawn
评论