如何提升FileSystemWatcher监控网络映射驱动器的运行可靠性
FileSystemWatcher 网络映射盘可靠性优化方案
你遇到的偶发FileNotFoundException核心是网络映射盘(SMB/CIFS协议)的固有特性导致:FileSystemWatcher的事件由本地系统内核回调触发,但远端文件服务器的元数据同步、本地SMB客户端的缓存刷新都存在异步延迟,事件上报时文件可能还没进入可被访问的状态,并非文件真的不存在。
以下是可落地的优化方案:
1. 新增文件可访问性预校验逻辑
在执行业务处理前,先做轻量的可访问性校验,不要直接调用业务逻辑打开文件:
- 先做3次间隔100ms的
File.Exists()校验,只要有一次返回true就进入下一步 - 存在性校验通过后,尝试以只读共享模式打开文件流,确认可以正常读取后再执行业务逻辑,示例代码如下:
private bool CheckFileAccessible(string filePath, int retryCount = 3) { for (int i = 0; i < retryCount; i++) { try { if (!File.Exists(filePath)) { Thread.Sleep(100); continue; } // 用共享读写模式打开,避免被其他写入进程占用 using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { // 可额外校验文件大小不为0,适配你的原有逻辑 return stream.Length > 0; } } catch (FileNotFoundException) { } catch (IOException) { } // 指数退避延迟,避免频繁重试占用资源 Thread.Sleep(100 * (i + 1)); } return false; }
2. 优化现有防抖去重逻辑
- 你当前使用的
Mutex是跨进程同步原语,如果你的场景不需要跨进程同步,换成C#原生的lock关键字即可,性能更高,也不会出现意外的跨进程锁占用问题 recentlyHandled列表建议替换为ConcurrentDictionary<string, DateTime>,按文件路径查询最后处理时间的效率远高于遍历列表,也更适配多线程场景- 网络盘场景下防抖等待时长建议调整到5秒,避免远端大文件写入、网络波动导致的状态同步延迟
3. 新增兜底处理机制
网络盘场景下FileSystemWatcher本身存在1%左右的误报/漏报概率,建议加两层兜底:
- 预校验失败的文件不要直接丢弃,加入重试队列,按2s/5s/10s的间隔做最多3次指数退避重试
- 新增小时级的全量扫盘逻辑,定时遍历监控目录,补处理未被正常消费的文件,覆盖极端的事件漏报场景
内容的提问来源于stack exchange,提问作者viraptor
相关产品推荐
相关产品推荐

