【发布时间】:2021-09-02 23:10:18
【问题描述】:
我无法理解tokio::try_run! 和在tokio::spawn 中运行的任务之间的交互,返回一个Err。
当我运行以下示例时:
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let h1 = tokio::spawn(async {
sleep(Duration::from_millis(100)).await;
// 1/0; commented for now
let v: Result<i32, ()> = Err(());
v
});
let h2 = tokio::spawn(async {
sleep(Duration::from_millis(500)).await;
println!("h2 didn't get canceled");
let v: Result<i32, ()> = Ok(2);
v
});
match tokio::try_join!(h1, h2) {
Ok((first, second)) => {
println!("try_join was successful, got {:?} and {:?}", first, second);
}
Err(err) => {
println!("try_join had an error: {:?}", err);
}
}
}
打印出来
h2 didn't get canceled
try_join was successful, got Err(()) and Ok(2)
但是,我希望它会打印出类似于我在 h1 中取消注释除以零时发生的情况:
thread 'tokio-runtime-worker' panicked at 'attempt to divide by zero', src/bin/select-test.rs:7:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
try_join had an error: JoinError::Panic(...)
try_join! 文档说
try_join!当所有分支返回 Ok 或第一个分支返回 Err 时宏返回。
但是,在我发布的示例中,h1 确实返回 Err 但 try_join! 执行 Ok 变体。此外,h2 不会被取消,它会运行到完成即使 h1 在数百毫秒之前已经失败了。我不明白这是否与文档相矛盾。此外,我似乎无法实现我想要做的事情,即当 h1 返回 Err 时取消 h2。
经过反复试验,我发现当我从 h1 和 h2 中删除 tokio::spawn 时,try_join! 确实以我预期的方式执行并调用了 Err 变体。不过,我不明白为什么这会有所作为。
谁能提供更多信息来解释为什么会出现这种行为?如果我希望在 h1 返回错误时取消 h2,是否需要删除 tokio::spawn 并放弃 h1 和 h2 之间的并行执行?
【问题讨论】:
标签: rust async-await rust-tokio