You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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管理来实现:

  1. 首先定义一个结构体来存放watcher实例:
use notify::RecommendedWatcher;
use std::sync::Mutex;

// 用于存储watcher的全局状态结构体
#[derive(Default)]
struct AppState {
    watcher: Mutex<Option<RecommendedWatcher>>,
}
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 14:28:24