using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespace JiShe.CollectBus.PluginFileWatcher { /// /// 文件监控相关工具类 /// public static class FileWatcherUtils { /// /// 检测文件是否被锁定 /// /// 要检查的文件路径 /// 如果文件被锁定则返回true,否则返回false public static bool IsFileLocked(string filePath) { if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) return false; try { using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) { // 文件可以被完全访问,没有被锁定 stream.Close(); } return false; } catch (IOException) { // 文件被锁定或正在被其他进程使用 return true; } catch (Exception) { // 其他错误(权限不足、路径无效等) return true; } } /// /// 尝试处理一个可能被锁定的文件 /// /// 文件路径 /// 成功解锁后要执行的操作 /// 健壮性配置 /// 处理结果:true表示成功处理,false表示处理失败 public static async Task TryHandleLockedFileAsync(string filePath, Func action, RobustnessConfig config) { if (!config.EnableFileLockDetection) { // 如果禁用了锁检测,直接执行操作 try { await action(); return true; } catch { return false; } } // 如果文件不存在或不是锁定状态,直接执行操作 if (!File.Exists(filePath) || !IsFileLocked(filePath)) { try { await action(); return true; } catch { return false; } } // 文件被锁定,根据策略处理 switch (config.LockedFileStrategy.ToLower()) { case "skip": // 跳过这个文件 Console.WriteLine($"文件被锁定,已跳过: {filePath}"); return false; case "retry": // 重试几次 for (int i = 0; i < config.FileLockRetryCount; i++) { await Task.Delay(config.FileLockRetryDelayMs); if (!IsFileLocked(filePath)) { try { await action(); Console.WriteLine($"文件锁已释放,成功处理: {filePath}"); return true; } catch { // 继续重试 } } } Console.WriteLine($"文件仍然被锁定,重试{config.FileLockRetryCount}次后放弃: {filePath}"); return false; case "log": default: // 只记录不处理 Console.WriteLine($"文件被锁定,已记录: {filePath}"); return false; } } /// /// 检查文件系统监控器是否健康 /// /// 要检查的监控器 /// 最后一次事件的时间 /// 健壮性配置 /// 如果监控器健康则返回true,否则返回false public static bool IsWatcherHealthy(FileSystemWatcher watcher, DateTime lastEventTime, RobustnessConfig config) { if (watcher == null || !watcher.EnableRaisingEvents) return false; // 如果配置了超时时间,检查是否超时 if (config.WatcherTimeoutSeconds > 0) { // 如果最后事件时间超过了超时时间,认为监控器可能已经失效 TimeSpan timeSinceLastEvent = DateTime.UtcNow - lastEventTime; if (timeSinceLastEvent.TotalSeconds > config.WatcherTimeoutSeconds) { // 执行一个简单的测试:尝试改变一些属性看是否抛出异常 try { var currentFilter = watcher.Filter; watcher.Filter = currentFilter; return true; // 如果没有异常,认为监控器仍然正常 } catch { return false; // 抛出异常,认为监控器已经失效 } } } // 默认情况下认为监控器健康 return true; } } }