我有一个正在接收数据的UDP套接字
pub async fn start() -> Result<(), std::io::Error> {
loop {
let mut data = vec![0; 1024];
socket.recv_from(&mut data).await?;
}
}
当前没有任何数据进入时,该代码当前在.await
上被阻止。我想从主线程正常关闭服务器,因此如何向该.await
发送信号应该停止睡眠并关闭它?
答案 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教程在select和channels上都有章节。
注意:该答案当前链接到Tokio的0.2版本,但是该答案也适用于Tokio 0.3。