157 lines
5.6 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace JiShe.CollectBus.PluginFileWatcher
{
/// <summary>
/// 文件监控相关工具类
/// </summary>
public static class FileWatcherUtils
{
/// <summary>
/// 检测文件是否被锁定
/// </summary>
/// <param name="filePath">要检查的文件路径</param>
/// <returns>如果文件被锁定则返回true否则返回false</returns>
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;
}
}
/// <summary>
/// 尝试处理一个可能被锁定的文件
/// </summary>
/// <param name="filePath">文件路径</param>
/// <param name="action">成功解锁后要执行的操作</param>
/// <param name="config">健壮性配置</param>
/// <returns>处理结果true表示成功处理false表示处理失败</returns>
public static async Task<bool> TryHandleLockedFileAsync(string filePath, Func<Task> 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;
}
}
/// <summary>
/// 检查文件系统监控器是否健康
/// </summary>
/// <param name="watcher">要检查的监控器</param>
/// <param name="lastEventTime">最后一次事件的时间</param>
/// <param name="config">健壮性配置</param>
/// <returns>如果监控器健康则返回true否则返回false</returns>
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;
}
}
}