rust 我在第一个分支上使用时雄select!宏. Process块时出现了问题,尽管有else子句

pgky5nke  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(228)

我尝试通过捕获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后,进程如我所料退出。

enxuqcxy

enxuqcxy1#

select!总是等待未来。参见the documentation
select!表达式的完整生命周期如下:
...
1.同时等待所有剩余<async expression>的结果。
1.当<async expression>返回一个值时,...
1.如果所有分支都被禁用,则计算else表达式。如果没有提供else分支,则panic。
直到 * 至少有一个 * 提供的future准备就绪,else甚至不会被考虑。因此,只对一个future使用select!没有意义;您可以始终对等待future的结果使用常规match
你可以做的是select!有两个分支:通道和 * 你的整个循环 *。这样,一旦通道有消息,循环就会被取消。

select! {
    Ok(_) = r_stop => {}
    () = async {
        loop {
            // do your actual work here
        }
    }
}

字符串
但是,如果任务不需要执行任何清理,请考虑使用Tokio's built-in abort functionality

let handle2 = tokio::spawn(async move {
    loop {
        // do stuff
    }
});

let abort = handle2.abort_handle();
tokio::spawn(async move {
    for _ in sigs.forever() {
        abort.abort();
    }
});


或者,如果您可能有多个事情要取消,请查看CancellationToken是否比您的oneshot使用更方便。

相关问题