如何使用Tokio远程关闭正在运行的任务

时间:2020-09-27 04:59:08

标签: rust rust-tokio

我有一个正在接收数据的UDP套接字

pub async fn start()  -> Result<(), std::io::Error> {
    loop {
        let mut data  = vec![0; 1024];
        socket.recv_from(&mut data).await?;
    }
}

当前没有任何数据进入时,该代码当前在.await上被阻止。我想从主线程正常关闭服务器,因此如何向该.await发送信号应该停止睡眠并关闭它?

1 个答案:

答案 0 :(得分:4)

如果要杀死多个任务,则应使用broadcast channel发送关闭消息。您可以将其与tokio::select!一起使用。

use tokio::sync::broadcast::Receiver;

// You may want to log errors rather than return them in this function.
pub async fn start(kill: Receiver<()>) -> Result<(), std::io::Error> {
    tokio::select! {
        output = real_start() => output,
        _ = kill.recv() => Err(...),
    }
}

pub async fn real_start() -> Result<(), std::io::Error> {
    loop {
        let mut data  = vec![0; 1024];
        socket.recv_from(&mut data).await?;
    }
}

然后杀死所有任务,在频道上发送消息。

当您只需要杀死一个任务时,更经常使用期货箱中的abortable工具。生成任务时,请执行以下操作:

let (task, handle) = abortable(start());
tokio::spawn(task);

然后,您可以通过调用abort方法来终止任务。

handle.abort();

当然,带有select!的频道也可以用于杀死单个任务,也许可以与oneshot频道而不是广播频道结合使用。

所有这些方法都保证real_start方法在.await被杀死。在两个.await之间运行代码时,无法终止该任务。

mini-redis项目包含一个可正常访问的服务器正常关闭示例。此外,Tokio教程在selectchannels上都有章节。

注意:该答案当前链接到Tokio的0.2版本,但是该答案也适用于Tokio 0.3。

相关问题