.NET 6 BackgroundService中FileSystemWatcher失效无日志输出问题
问题根本原因
FileSystemWatcher对象被提前释放:MyWatcher方法中使用using var声明watcher实例,该声明的生命周期绑定为当前方法作用域,MyWatcher执行完成后会自动调用watcher的Dispose()方法销毁对象,销毁后的watcher自然无法响应任何文件变更事件。- 监控路径转义错误:传入的路径字符串
$"C:\test"未做逐字处理,C#语法中\t会被解析为制表符转义字符,程序实际尝试绑定的监控路径为C:<制表符>est,和预期的C:\test路径完全不符,无法绑定到目标目录。 - 等待逻辑存在性能缺陷:
ExecuteAsync中的空while循环属于忙等逻辑,会无意义占满CPU核心,极端情况下可能导致事件调度异常。
修复方案
- 调整
FileMonitor的实现逻辑,将FileSystemWatcher作为类的长生命周期成员持有,避免被提前释放,同时实现IDisposable接口在服务停止时正确释放资源。 - 修正路径字符串的转义问题,使用逐字字符串前缀
@保证路径解析正确。 - 替换空循环的忙等逻辑,使用支持取消令牌的异步等待实现低开销阻塞,避免CPU空转。
- 增加watcher的错误事件监听,方便后续排查权限、缓冲区溢出等运行时问题。
修复后完整代码
FileMonitor 类实现
public class FileMonitor : IDisposable { private FileSystemWatcher _watcher; public void StartWatch(string targetFolder) { // 释放已存在的旧watcher实例 _watcher?.Dispose(); _watcher = new FileSystemWatcher(targetFolder); // 补充LastWrite过滤,普通文本内容修改默认触发该类型通知 _watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastWrite; // 绑定事件 _watcher.Changed += OnChanged; _watcher.Created += OnCreated; _watcher.Error += OnWatcherError; _watcher.Filter = "*.txt"; _watcher.EnableRaisingEvents = true; } private void OnChanged(object sender, FileSystemEventArgs e) { if (e.ChangeType != WatcherChangeTypes.Changed) return; Console.WriteLine($"Changed: {e.FullPath}"); } private void OnCreated(object sender, FileSystemEventArgs e) { Console.WriteLine($"Created: {e.FullPath}"); } private void OnWatcherError(object sender, ErrorEventArgs e) { Console.WriteLine($"Monitor error: {e.GetException().Message}"); } public void Dispose() { _watcher?.Dispose(); } }
BackgroundService 执行逻辑
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using var monitor = new FileMonitor(); // 使用逐字字符串修正路径转义问题 monitor.StartWatch(@"C:\test"); try { // 低开销等待服务停止信号,替代空while循环 await Task.Delay(Timeout.Infinite, stoppingToken); } catch (OperationCanceledException) { // 服务停止触发的取消为预期行为,正常处理即可 Console.WriteLine("File monitor service is shutting down..."); } }
补充排查点:如果部署为Windows服务后仍无事件输出,检查服务配置的运行账户是否拥有目标监控目录的读取、目录遍历权限;如果目录文件变更频率极高,可适当调大
FileSystemWatcher.InternalBufferSize属性(建议不超过64KB)避免缓冲区溢出丢事件。
内容的提问来源于stack exchange,提问作者Saghar Francis
相关产品推荐
相关产品推荐

