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

.NET 6 BackgroundService中FileSystemWatcher失效无日志输出问题

问题根本原因
  • FileSystemWatcher对象被提前释放:MyWatcher方法中使用using var声明watcher实例,该声明的生命周期绑定为当前方法作用域,MyWatcher执行完成后会自动调用watcher的Dispose()方法销毁对象,销毁后的watcher自然无法响应任何文件变更事件。
  • 监控路径转义错误:传入的路径字符串$"C:\test"未做逐字处理,C#语法中\t会被解析为制表符转义字符,程序实际尝试绑定的监控路径为C:<制表符>est,和预期的C:\test路径完全不符,无法绑定到目标目录。
  • 等待逻辑存在性能缺陷:ExecuteAsync中的空while循环属于忙等逻辑,会无意义占满CPU核心,极端情况下可能导致事件调度异常。
修复方案
  1. 调整FileMonitor的实现逻辑,将FileSystemWatcher作为类的长生命周期成员持有,避免被提前释放,同时实现IDisposable接口在服务停止时正确释放资源。
  2. 修正路径字符串的转义问题,使用逐字字符串前缀@保证路径解析正确。
  3. 替换空循环的忙等逻辑,使用支持取消令牌的异步等待实现低开销阻塞,避免CPU空转。
  4. 增加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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:06:22