Tokio mpsc channel跨异步任务传输消息失效问题咨询
问题原因
你的问题核心是watcher变量被提前释放了:
- 调用
watch_with_task函数时,RecommendedWatcher实例创建在watch_with_task的函数栈上,你只把接收端rx移动到了tokio::spawn生成的子任务中,watcher本身并没有被移入子任务。 watch_with_task返回JoinHandle之后函数就执行结束,栈上的watcher变量会被自动析构(drop)。RecommendedWatcher被析构时会终止内部的事件监听线程,同时持有的发送端tx也会被释放,此时mpsc channel的所有发送端都已关闭,rx.next().await会直接返回None,循环退出,子任务就结束了。- 而
watch_without_task能正常工作的原因是watcher和rx的生命周期都绑定在这个异步函数的作用域中,函数一直阻塞在事件循环上,watcher不会被提前析构,channel会一直保持可用状态。
修复方法
只需要把watcher也移动到子任务的闭包中,让它的生命周期和子任务绑定即可,同时注意路径的生命周期处理:
fn watch_with_task(path: &str) -> tokio::task::JoinHandle<()> { let (mut watcher, mut rx) = async_watcher().unwrap(); let path = path.to_string(); // 转换为String持有,避免生命周期问题 tokio::spawn(async move { // watch操作移入子任务内部执行 watcher .watch(Path::new(&path), RecursiveMode::NonRecursive) .unwrap(); eprintln!("Watch task spawned"); while let Some(res) = rx.next().await { match res { Ok(event) => eprintln!("File changed: {:?}", event), Err(e) => eprintln!("Watch error: {:?}", e), } } eprintln!("Watch task finished"); }) }
修改后记得在main函数中await返回的JoinHandle,否则主函数提前退出也会直接终止整个程序。
内容的提问来源于stack exchange,提问作者Timmmm
相关产品推荐
相关产品推荐

