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

动态创建FileSystemWatcher无法监控网络驱动器,求可行方案

问题描述

我正在开发一款可监控多个文件夹的应用,参考了几个动态创建FileSystemWatcher的方案,但测试后发现这些方案仅能监控本地文件夹,无法监控网络驱动器。

我的动态实现代码如下:

public static void StartMultipleWatchers(string path)
{
    string[] paths = path.Split(',');

    foreach (string folderPath in paths)
    {
          try
          {
              string folderPathtrim = folderPath.Trim();
              WatchFile(folderPathtrim);
           }
           catch(Exception ex)
           {
               Logger.Error(ex);
           }
        }
    }

private static void WatchFile(string monitoredDir)
{
   FileSystemWatcher fsw = new FileSystemWatcher(monitoredDir, "*.gz");
   fsw.Changed += new FileSystemEventHandler(OnChanged);
   fsw.Created += new FileSystemEventHandler(OnCreated);
   fsw.EnableRaisingEvents = true;
   fsw.IncludeSubdirectories = true;
   Logger.Info($"Started loop Monitor of Folder: {monitoredDir}");
}

private static void OnCreated(object sender, FileSystemEventArgs e)
{
    FileInfo fileInfo = new FileInfo(e.FullPath);
    string value = $"Created: {e.FullPath}";
    Logger.Info(value);    
}

该方案仅对本地文件夹有效,或仅监控单个网络文件夹时有效。

之后我尝试了手动逐个创建FileSystemWatcher的方案:

public static void TestManualWatchers()
{
   var fsw1 = new FileSystemWatcher(@"\\lap.org.com\tool_data_odp_ws\metrology\CIM\DATA_READY\");
   var fsw2 = new FileSystemWatcher(@"C:\TestPath\");
   fsw1.Changed += OnChanged;
   fsw1.Created += OnCreated;
   fsw1.EnableRaisingEvents = true;
   fsw1.IncludeSubdirectories = true;

   fsw2.Changed += OnChanged;
   fsw2.Created += OnCreated;
   fsw2.EnableRaisingEvents = true;
   fsw2.IncludeSubdirectories = true;    
   Logger.Info($"Started watching manual double files");

 }

此方案可正常监控本地和网络文件夹。

请问两种实现的差异是什么?是否存在可行的动态创建多个FileSystemWatcher的方法?


问题分析与解答

两种实现的核心差异

动态创建方案中,FileSystemWatcher实例是局部变量,在WatchFile方法执行完毕后,没有被外部引用持有,会被.NET的垃圾回收器(GC)标记为可回收对象并销毁。尤其是网络文件夹的监控依赖持续的连接,GC回收后连接断开,自然无法触发事件。

而手动创建方案中,fsw1和fsw2虽然也是方法内的局部变量,但如果方法所在的类实例或静态上下文被持续持有(比如应用主线程未退出),这些实例会被隐式保留,不会被GC回收,因此能持续正常工作。

另外,动态方案中给FileSystemWatcher指定了过滤条件"*.gz",而手动方案没有设置过滤,这也可能导致部分场景下动态方案看似“失效”(比如网络文件夹中创建的非gz文件不会触发事件),但这不是核心原因。

可行的动态创建解决方案

要让动态创建的FileSystemWatcher持续有效,核心是保留对每个实例的引用,避免被GC回收。具体修改如下:

  1. 定义静态集合存储所有监控器实例:
// 全局静态集合,持有所有监控器实例,防止被GC回收
private static List<FileSystemWatcher> _watchers = new List<FileSystemWatcher>();
  1. 在WatchFile方法中,将创建的实例添加到集合:
private static void WatchFile(string monitoredDir)
{
   FileSystemWatcher fsw = new FileSystemWatcher(monitoredDir, "*.gz");
   fsw.Changed += OnChanged;
   fsw.Created += OnCreated;
   fsw.EnableRaisingEvents = true;
   fsw.IncludeSubdirectories = true;
   // 添加到集合保留引用
   _watchers.Add(fsw);
   Logger.Info($"Started loop Monitor of Folder: {monitoredDir}");
}
  1. 可选:停止监控时清理资源:
public static void StopAllWatchers()
{
    foreach(var watcher in _watchers)
    {
        watcher.EnableRaisingEvents = false;
        watcher.Dispose();
    }
    _watchers.Clear();
    Logger.Info("All watchers stopped.");
}

修改后,动态创建的FileSystemWatcher实例会被集合持有,不会被GC回收,本地和网络文件夹都能正常监控。另外需确保应用有足够权限访问目标共享文件夹,且网络连接稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:45:37