WPF应用中FileSystemWatcher事件不触发问题求助
问题原因
你的代码核心问题是在构造函数中使用using var声明FileSystemWatcher实例,导致对象在构造函数执行完毕后被立即释放,根本没有机会执行文件监听逻辑。using var语法会在变量所属的代码作用域结束时自动调用对象的Dispose()方法释放资源。你将watcher定义为构造函数的局部变量,构造函数执行完成就会退出该变量的作用域,watcher直接被释放,所有绑定的事件自然不会触发。
控制台版本可以正常运行是因为官方示例在watcher启动后添加了阻塞逻辑(如等待用户输入退出指令),watcher的作用域会持续到程序退出前,不会被提前释放。
此外你后续还会遇到第二个问题:FileSystemWatcher的事件默认在后台线程触发,直接在事件处理中调用MessageBox或操作WPF UI控件会抛出跨线程访问异常。
修复方案
按照以下步骤调整代码即可:
- 将
FileSystemWatcher声明为MainWindow类的实例字段,不要使用using修饰,将它的生命周期和窗口绑定,避免被提前释放或被GC回收。 - 所有事件处理逻辑中涉及UI操作的部分,必须通过UI线程调度器调度执行,避免跨线程异常。
- 在窗口关闭事件中主动Dispose watcher,释放系统资源。
修正后的核心代码参考:
public partial class MainWindow : Window { // 声明为类实例字段,生命周期随窗口存在 private readonly FileSystemWatcher _watcher; public MainWindow() { InitializeComponent(); // 初始化watcher,不要加using关键字 _watcher = new FileSystemWatcher(@"C:\Users\Connor\Desktop\Test") { NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size, Filter = "*.txt", IncludeSubdirectories = true, EnableRaisingEvents = true }; // 绑定事件 _watcher.Changed += OnChanged; _watcher.Created += OnCreated; _watcher.Deleted += OnDeleted; _watcher.Renamed += OnRenamed; _watcher.Error += OnError; // 窗口关闭时主动释放watcher资源 Closed += (_, _) => _watcher.Dispose(); } private void OnChanged(object sender, FileSystemEventArgs e) { if (e.ChangeType != WatcherChangeTypes.Changed) return; // 调度到UI线程执行UI操作 Dispatcher.Invoke(() => { MessageBox.Show($"Changed: {e.FullPath}"); }); } private void OnCreated(object sender, FileSystemEventArgs e) { string value = $"Created: {e.FullPath}"; Dispatcher.Invoke(() => { MessageBox.Show(value); }); } private void OnDeleted(object sender, FileSystemEventArgs e) { // Debug.WriteLine不需要调度到UI线程,可直接执行 Debug.WriteLine($"Deleted: {e.FullPath}"); } private void OnRenamed(object sender, RenamedEventArgs e) { Dispatcher.Invoke(() => { MessageBox.Show($"Renamed:"); MessageBox.Show($" Old: {e.OldFullPath}"); MessageBox.Show($" New: {e.FullPath}"); }); } private void OnError(object sender, ErrorEventArgs e) { Dispatcher.Invoke(() => { PrintException(e.GetException()); }); } private void PrintException(Exception? ex) { if (ex != null) { MessageBox.Show($"Message: {ex.Message}"); MessageBox.Show("Stacktrace:"); MessageBox.Show(ex.StackTrace); PrintException(ex.InnerException); } } }
注意:不要尝试将watcher存为构造函数局部变量且不加using,局部变量会被GC在不确定的时间点回收,回收后事件同样会随机失效,必须存为类的实例字段保证生命周期可控。
内容的提问来源于stack exchange,提问作者Connor
相关产品推荐
相关产品推荐

