Rust + Tokio 异步实战:select! 多路等待、任务取消与优雅退出
test12026-09-130 次阅读
问题背景
异步服务常需要"等任意一个条件先满足":超时、外部信号、子任务完成。Tokio 的 select! 宏能在多个异步分支中只等待第一个完成的,其余分支被丢弃,非常适合做超时控制与优雅关闭。
select! 做超时
use tokio::time::{sleep, Duration};
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, rx) = oneshot::channel::<()>();
tokio::select! {
_ = sleep(Duration::from_secs(3)) => {
println!("超时:任务被取消");
}
_ = rx => {
println!("收到信号,正常退出");
}
}
}
用 JoinHandle 主动取消任务
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let handle = tokio::spawn(async {
loop {
println!("工作中…");
sleep(Duration::from_secs(1)).await;
}
});
sleep(Duration::from_millis(500)).await;
handle.abort(); // 显式取消,任务立即结束
let _ = handle.await; // 拿到 JoinError(Cancelled)
}
配合信号做优雅退出
use tokio::signal;
#[tokio::main]
async fn main() {
let ctrl_c = async {
signal::ctrl_c().await.ok();
};
tokio::select! {
_ = ctrl_c => println!("收到 Ctrl+C,开始回收资源"),
_ = serve() => {},
}
}
async fn serve() {
// 主服务循环
}
要点
- select! 中未完成的 Future 会被 drop,其内部持有的资源随之释放;注意闭包捕获的变量所有权。
- abort 是"硬取消",不会执行被取消任务里的 defer 逻辑,关键清理要放到 select 之外或监听取消信号。
- 用 biased; 修饰符可改变分支轮询优先级,避免某些分支永远饿死。
T
test1
文章作者
问题背景 异步服务常需要"等任意一个条件先满足":超时、外部信号、子任务完成。Tokio 的 select! 宏能在多...
- 分类
- 技术
- 发布时间
- 2026-09-13
- 字数
- 约 1267 字
- 阅读
- 0 次
