如何通过FileSystemWatcher检测目录被替换的事件
如何捕获FileSystemWatcher的目录替换事件
我之前也踩过这个坑!Windows系统里的目录替换操作,本质上是先删除旧目录,再创建同名新目录的组合动作,所以默认的FileSystemWatcher只会触发Created事件,不会像文件那样触发Changed。要捕获目录替换,得通过监听Deleted和Created事件,结合时间差来判断。
解决思路
核心逻辑是:记录被删除的目录信息(名称+删除时间),当Created事件触发时,检查最近是否有同名目录被删除,若时间差在合理范围内,就判定为目录替换操作。
具体实现步骤
1. 准备缓存记录删除的目录
声明一个线程安全的字典,用来存储被删除的目录全路径和对应的删除时间:
private Dictionary<string, DateTime> _deletedDirectories = new Dictionary<string, DateTime>(); // 替换操作的时间阈值,可根据实际场景调整(比如1秒) private readonly TimeSpan _replaceThreshold = TimeSpan.FromSeconds(1);
2. 修改FileSystemWatcher配置
添加Deleted事件的监听,同时调整事件处理逻辑(把Created事件单独处理,方便判断替换):
watcher = new FileSystemWatcher(); // 用Path.Combine拼接路径更规范,避免转义符问题 watcher.Path = Path.Combine(folder, "INPUT"); // 保持你的NotifyFilter配置,确保能捕获目录相关事件 watcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.Attributes; watcher.Changed += eventRaised; // 单独处理Created事件,用于判断替换 watcher.Created += OnDirectoryCreated; // 添加Deleted事件监听,记录删除的目录 watcher.Deleted += OnDirectoryDeleted; watcher.IncludeSubdirectories = true; watcher.EnableRaisingEvents = true; watcher.Error += OnError;
3. 实现Deleted和Created事件处理方法
private void OnDirectoryDeleted(object sender, FileSystemEventArgs e) { if (e.ChangeType == WatcherChangeTypes.Deleted) { // 加锁保证线程安全,因为FileSystemWatcher事件在后台线程触发 lock (_deletedDirectories) { var dirPath = e.FullPath; if (_deletedDirectories.ContainsKey(dirPath)) _deletedDirectories[dirPath] = DateTime.Now; else _deletedDirectories.Add(dirPath, DateTime.Now); } } } private void OnDirectoryCreated(object sender, FileSystemEventArgs e) { if (e.ChangeType == WatcherChangeTypes.Created) { lock (_deletedDirectories) { var dirPath = e.FullPath; if (_deletedDirectories.TryGetValue(dirPath, out DateTime deleteTime)) { var timeDiff = DateTime.Now - deleteTime; if (timeDiff <= _replaceThreshold) { // 这里就是目录替换事件,执行你的自定义逻辑 Console.WriteLine($"目录 {dirPath} 已被替换"); // 处理完成后移除记录,避免重复判断 _deletedDirectories.Remove(dirPath); return; } // 时间差超过阈值,说明是普通创建,移除旧记录 _deletedDirectories.Remove(dirPath); } } // 普通创建事件,调用原来的处理逻辑 eventRaised(sender, e); } }
注意事项
- 线程安全:一定要用
lock保护字典的操作,因为FileSystemWatcher的事件是在后台线程触发的,多线程操作共享集合会有线程安全问题。 - 阈值调整:如果你的目录替换操作耗时较长(比如目录里文件很多),可以适当调大
_replaceThreshold的时间值。 - 误判情况:如果用户手动删除目录后又立即创建同名目录,这个逻辑会判定为替换,但这和实际的替换操作行为一致,业务层面通常可以接受。
内容的提问来源于stack exchange,提问作者Santhosh Nayak
相关产品推荐
相关产品推荐

