Tauri setup内的notify文件监视器无法触发问题
Tauri中setup内的notify文件监视器无法触发事件
我在基础Tauri应用里集成notify文件监视器时遇到问题:Tauri setup外部创建的watcher1能正常触发事件,但setup内部的watcher2完全没反应。
相关代码如下:
use notify::{RecursiveMode, Result, Watcher}; use std::path::Path; fn main() -> Result<()> { let mut watcher1 = notify::recommended_watcher(move |res| match res { Ok(event) => { // 能正常打印 println!("watcher1 event: {:?}", event); } Err(e) => println!("watch error: {:?}", e), }) .expect("error creating file watcher"); watcher1 .watch(Path::new("."), RecursiveMode::Recursive) .expect("error watching folder"); tauri::Builder::default() .setup(|_app| { let mut watcher2 = notify::recommended_watcher(move |res| match res { Ok(event) => { // 完全不打印 println!("watcher2 event: {:?}", event); } Err(e) => println!("watch error: {:?}", e), }) .expect("error creating file watcher"); watcher2 .watch(Path::new("."), RecursiveMode::Recursive) .expect("error watching folder"); Ok(()) }) .run(tauri::generate_context!()) .expect("error while running tauri builder"); Ok(()) }
测试步骤:
- 克隆项目后执行
yarn && yarn tauri dev - 进入
src-tauri目录修改文件(比如执行touch random-file && rm random-file)
排查情况:
- 移除watcher1后,watcher2依然无响应
- 添加打印语句确认watcher2已经被正常创建
问题原因
notify的Watcher实例需要持续保持存活才能监听文件系统事件。在setup函数里创建的watcher2是局部变量,当setup函数执行完毕后,这个变量就会被Rust的所有权系统销毁(drop),自然无法再触发后续的事件。而watcher1在main函数的顶层作用域,只要程序运行就会一直存在,所以能正常工作。
解决方法
需要把watcher2存储到Tauri应用的全局状态里,让它在应用生命周期内保持存活。可以用Tauri的State管理来实现:
- 首先定义一个结构体来存放watcher实例:
use notify::RecommendedWatcher; use std::sync::Mutex; // 用于存储watcher的全局状态结构体 #[derive(Default)] struct AppState { watcher: Mutex<Option<RecommendedWatcher>>, }
- 修改main函数,将watcher2存入AppState:
use notify::{RecursiveMode, Result, Watcher}; use std::path::Path; use std::sync::Mutex; #[derive(Default)] struct AppState { watcher: Mutex<Option<RecommendedWatcher>>, } fn main() -> Result<()> { let mut watcher1 = notify::recommended_watcher(move |res| match res { Ok(event) => { println!("watcher1 event: {:?}", event); } Err(e) => println!("watch error: {:?}", e), }) .expect("error creating file watcher"); watcher1 .watch(Path::new("."), RecursiveMode::Recursive) .expect("error watching folder"); tauri::Builder::default() // 注册全局状态 .manage(AppState::default()) .setup(|app| { // 获取全局状态的可变引用 let state = app.state::<AppState>(); let watcher = notify::recommended_watcher(move |res| match res { Ok(event) => { println!("watcher2 event: {:?}", event); } Err(e) => println!("watch error: {:?}", e), }) .expect("error creating file watcher"); watcher .watch(Path::new("."), RecursiveMode::Recursive) .expect("error watching folder"); // 将watcher存入全局状态,避免被销毁 *state.watcher.lock().unwrap() = Some(watcher); Ok(()) }) .run(tauri::generate_context!()) .expect("error while running tauri builder"); Ok(()) }
这样修改后,watcher2会被存储在Tauri的全局状态中,只要应用在运行,它就会保持存活,就能正常触发文件系统事件了。
内容的提问来源于stack exchange,提问作者Kaspar Emanuel
相关产品推荐
相关产品推荐

