Tokio Select Timeout Cancellation
Bound async operations with tokio::select over a timeout future, racing work against deadlines and handling branch outcomes.
Code
use std::time::Duration;
use tokio::time::{sleep, timeout};
async fn fetch_quote(symbol: &'static str) -> String {
sleep(Duration::from_millis(300)).await;
format!("{symbol}=142.50")
}
async fn with_deadline(symbol: &'static str) -> Result<String, String> {
let deadline = Duration::from_millis(150);
// select 让慢操作与超时竞争,先完成者胜出
tokio::select! {
quote = fetch_quote(symbol) => Ok(quote),
_ = sleep(deadline) => Err(format!("{symbol} exceeded {deadline:?}")),
}
}
async fn stream_with_timeout() -> Vec<String> {
let mut received = Vec::new();
let (tx, mut rx) = tokio::sync::mpsc::channel(8);
tokio::spawn(async move {
for i in 0..5 {
sleep(Duration::from_millis(40)).await;
if tx.send(format!("tick-{i}")).await.is_err() {
break; // 接收端已放弃
}
}
});
loop {
let next = tokio::select! {
msg = rx.recv() => msg,
_ = sleep(Duration::from_millis(120)) => None,
};
match next {
Some(msg) => received.push(msg),
None => break, // 通道关闭或超时
}
}
received
}
#[tokio::main]
async fn main() {
println!("{:?}", with_deadline("APPL").await);
let wrapped = timeout(Duration::from_millis(500), fetch_quote("MSFT")).await;
println!("{:?}", wrapped.map(|s| s.len()));
println!("{:?}", stream_with_timeout().await);
}Report a problem with this exampleOpens a pre-filled issue on GitHub.