我尝试通过捕获SIGTERM或SIGINT之类的信号来设置一个通道以优雅地退出流程。为了在默认情况下执行业务逻辑,我编写了如下代码:
let (t_stop, mut r_stop) = oneshot::channel::<Empty>();
let handle1 = tokio::spawn(async move {
for _ in sigs.forever() {
t_stop.send(Empty {}).expect("stop failed");
return;
}
});
...
let handle2 = tokio::spawn(async move {
loop {
select! {
Ok(_) = &mut r_stop =>{
return;
}
else => {
info!("default");
...
}
};
}
});
字符串
但是,令人沮丧的是,进程似乎在第一个分支上受阻。
为了解决这个问题,我试着在时雄的主页上读取文档。不幸的是,它只是叙述了除非其他分支模式都不匹配,否则不会执行else分支。我预计Ok(_) = &mut r_stop
在模式匹配失败,直到信号发送,所以应该执行else子句。顺便说一下,在按下center +c后,进程如我所料退出。
1条答案
按热度按时间enxuqcxy1#
select!
总是等待未来。参见the documentation:select!表达式的完整生命周期如下:
...
1.同时等待所有剩余
<async expression>
的结果。1.当
<async expression>
返回一个值时,...1.如果所有分支都被禁用,则计算
else
表达式。如果没有提供else分支,则panic。直到 * 至少有一个 * 提供的future准备就绪,
else
甚至不会被考虑。因此,只对一个future使用select!
没有意义;您可以始终对等待future的结果使用常规match
。你可以做的是
select!
有两个分支:通道和 * 你的整个循环 *。这样,一旦通道有消息,循环就会被取消。字符串
但是,如果任务不需要执行任何清理,请考虑使用Tokio's built-in abort functionality:
型
或者,如果您可能有多个事情要取消,请查看
CancellationToken
是否比您的oneshot使用更方便。