Rust是否具备与C#类似的Cancellation Token(取消令牌)机制?
在Rust中实现类似C# CancellationToken的优雅退出方案
你的问题核心是:无限循环未响应系统终止信号(如SIGTERM、SIGINT),导致操作系统只能等待超时后强制杀死进程,进而拉长重启耗时。Rust没有内置和C# CancellationToken完全一致的类型,但可以通过信号捕获+取消标记的组合实现等价的优雅退出逻辑,下面分同步、异步两种场景给出具体实现:
同步程序场景
依赖ctrlc crate捕获系统中断信号,配合原子布尔值作为取消标记,让循环能及时响应退出信号:
1. 添加依赖
在Cargo.toml中加入:
[dependencies] ctrlc = "3.4"
2. 实现代码
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; fn main() { // 创建原子布尔值作为运行标记,线程安全 let running = Arc::new(AtomicBool::new(true)); let signal_handler_running = running.clone(); // 注册信号处理函数:收到终止信号时将标记设为false ctrlc::set_handler(move || { signal_handler_running.store(false, Ordering::SeqCst); eprintln!("收到终止信号,准备退出循环"); }).expect("无法设置信号处理器"); // 带取消检查的无限循环 while running.load(Ordering::SeqCst) { // 替换为你的任务逻辑 println!("执行任务中..."); // 注意:避免长时间阻塞,确保循环能定期检查标记 std::thread::sleep(std::time::Duration::from_secs(1)); } println!("循环已退出,程序优雅终止"); }
异步程序场景(基于Tokio)
Tokio提供了CancellationToken类型,结合信号捕获可以更简洁地实现异步任务的取消:
1. 添加依赖
[dependencies] tokio = { version = "1.0", features = ["full"] }
2. 实现代码
use tokio::signal::unix::{signal, SignalKind}; use tokio::sync::CancellationToken; #[tokio::main] async fn main() { let cancellation_token = CancellationToken::new(); let token_clone = cancellation_token.clone(); // 后台线程捕获SIGTERM和SIGINT信号,触发取消 tokio::spawn(async move { let mut sigterm = signal(SignalKind::terminate()).expect("无法捕获SIGTERM"); let mut sigint = signal(SignalKind::interrupt()).expect("无法捕获SIGINT"); tokio::select! { _ = sigterm.recv() => { eprintln!("收到SIGTERM,触发任务取消"); token_clone.cancel(); } _ = sigint.recv() => { eprintln!("收到SIGINT,触发任务取消"); token_clone.cancel(); } } }); // 带取消检查的异步循环 loop { tokio::select! { // 等待取消信号触发 _ = cancellation_token.cancelled() => { eprintln!("取消信号生效,退出循环"); break; } // 执行你的异步任务 _ = tokio::time::sleep(tokio::time::Duration::from_secs(1)) => { println!("执行异步任务中..."); } } } println!("程序优雅终止"); }
关键注意事项
- 循环中不能有过长时间的阻塞操作,否则即使收到终止信号,也无法及时检查取消标记。如果必须使用阻塞IO,建议设置超时或改用非阻塞API。
- 系统重启时,OS会先发送
SIGTERM给进程,等待一段超时时间后才会发送SIGKILL强制杀死进程。优雅退出逻辑能让进程在收到SIGTERM后立即停止,大幅缩短重启耗时。
内容的提问来源于stack exchange,提问作者Milen Denev
相关产品推荐
相关产品推荐

