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

FileSystemWatcher监控UNC路径失效:是实现问题还是需替代方案?

问题描述

我开发了一个服务用于监控多个UNC路径,目标是监听指定文件夹,当有新的.gz文件创建时,触发独立的.NET控制台文件转换程序执行转换操作。当前实现的FileSystemWatcher逻辑仅对本地目录有效,无法正常监控UNC路径(示例路径:\\tooltypedir.companyname.com\somedir\topfolder\toolvariant\data_ready\)。现咨询:是我的FileSystemWatcher实现存在错误,还是有更可靠的替代方案?


核心代码

static List<String> filesInProgress = new List<string>();
static List<FileSystemWatcher> listOfWatchers = new List<FileSystemWatcher>();

protected override void OnStart(string[] args)
{
    UserSettingsUtil.InitServiceSettings();
    _applicationExeDir = UserSettingsUtil.TDX2KlarfExePath;
    _tdx2KlarfExeName = UserSettingsUtil.TDX2KlarfApplicationExeName;
    _foldersToWatch = UserSettingsUtil.FoldersWatched;
    Watch();
}

监控逻辑代码

private static void Watch()
{
    string[] paths = _foldersToWatch.Split(',');
    foreach (string dir in paths)
    {
        string dirTrim = dir.Trim();
        if (Directory.Exists(dirTrim))
        {
            FileSystemWatcher fileWatcher = new FileSystemWatcher();
            fileWatcher.Path = dirTrim;
            fileWatcher.Created += File_Created;
            //fileWatcher.Changed += OnChanged;
            fileWatcher.Filter = "*.gz";
            fileWatcher.IncludeSubdirectories = true;
            fileWatcher.EnableRaisingEvents = true;
            Logger.Info($"Started service monitoring {dirTrim}");
            listOfWatchers.Add(fileWatcher);
        }
    }
}

private static void File_Created(object sender, FileSystemEventArgs e)
{
    if (e.ChangeType == WatcherChangeTypes.Created)
    {
        if (Directory.Exists(e.FullPath))
        {
            foreach (string file in Directory.GetFiles(e.FullPath))
            {
                var eventArgs = new FileSystemEventArgs(
                    WatcherChangeTypes.Created,
                    Path.GetDirectoryName(file),
                    Path.GetFileName(file));
                //Logger.Info($"Inner Loop file create {file}");
                File_Created(sender, eventArgs);
            }
        }
        else
        {
            var fullFilePath = e.FullPath;
            Logger.Info("{0} created.", fullFilePath);
            if (!filesInProgress.Contains(fullFilePath))
            {
                Thread converter = new Thread(ConfigureAndStartProcess);
                converter.Start(fullFilePath);
                filesInProgress.Add(fullFilePath);
            }
        }
    }
}

服务停止逻辑代码

protected override void OnStop()
{
    //watcher.Dispose();
    if (listOfWatchers.Count > 0)
    {
        foreach (var dirWatcher in listOfWatchers)
        {
            dirWatcher.Dispose();
        }
    }
}

解决方案分析

一、现有FileSystemWatcher实现的问题排查

FileSystemWatcher本身支持UNC路径,但你的代码存在几个可能导致监控失效的问题:

  1. 权限不足

    • 若服务以本地系统账户运行,访问UNC路径时大概率没有足够权限。需将服务运行账户改为拥有目标UNC路径读写权限的域账户或本地账户。
    • 验证方式:用服务运行账户手动登录系统,确认能正常访问、读写目标UNC路径下的文件。
  2. Created事件的局限性

    • 网络文件复制到UNC路径时,Created事件可能在文件未完全写入时就触发,后续处理会出错;部分SMB网络文件系统对Created事件的通知支持不稳定,容易丢事件。
    • 代码中递归调用File_Created处理子目录文件,存在重复触发或栈溢出风险。
  3. 未处理错误事件

    • 监控UNC路径时易出现网络中断、权限变化等错误,你未订阅Error事件,无法排查具体故障。建议添加:
      fileWatcher.Error += OnWatcherError;
      
      配套实现错误日志记录:
      private static void OnWatcherError(object sender, ErrorEventArgs e)
      {
          Logger.Error($"监控器错误: {e.GetException().Message}");
      }
      
  4. 线程安全问题

    • List<string>并非线程安全集合,多线程操作filesInProgress会引发异常或数据错误,建议改用ConcurrentDictionary<string, object>:
      static ConcurrentDictionary<string, object> filesInProgress = new ConcurrentDictionary<string, object>();
      
      修改判断逻辑:
      if (filesInProgress.TryAdd(fullFilePath, null))
      {
          Thread converter = new Thread(ConfigureAndStartProcess);
          converter.Start(fullFilePath);
      }
      

二、更可靠的替代方案

若原生FileSystemWatcher的网络稳定性无法满足需求,可考虑以下方案:

1. 定时轮询目录

实现简单、稳定性高,适合对实时性要求不极致的场景:

  • 每隔固定时间(如10秒)扫描目标UNC路径及其子目录,对比上次扫描的文件列表,筛选新增的.gz文件。
  • 用HashSet<string>存储已处理文件路径,避免重复操作。
  • 注意:扫描大目录时需优化性能,避免阻塞服务主线程。

2. 使用第三方优化库

  • Microsoft.Extensions.FileSystemGlobbing:可高效扫描目录,结合定时任务实现监控。
  • 部分开源DirectoryWatcher组件:针对网络路径做了专门优化,稳定性优于原生FileSystemWatcher。

临时修复建议

先给现有代码添加错误事件处理,检查服务运行账户权限,将filesInProgress替换为线程安全集合,验证是否能正常监控UNC路径。若仍无法解决,再切换到定时轮询方案。

内容的提问来源于stack exchange,提问作者Datboydozy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:10:34