当前位置: 首页 > article >正文

C#高效异步文件监控与日志记录工具

优势

  1. 异步处理:提高了文件变化处理的效率,避免了阻塞主线程。
  2. 线程安全:使用了线程安全的队列来避免多线程环境下的竞态条件。
  3. 日志记录:异步日志记录减少了对主线程的干扰,并且能够处理大量事件。
  4. 灵活配置:可以通过配置文件调整监控目录和过滤规则,增加了灵活性。
  5. 支持子目录:可以监控指定目录及其所有子目录中的文件变化。
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

// 定义一个类来封装文件变化的事件信息
public class FileChangeEvent
{
    public string FilePath { get; set; }
    public WatcherChangeTypes ChangeType { get; set; }
    public DateTime ChangeTime { get; set; }
}

class Program
{
    private static FileSystemWatcher _fileSystemWatcher; // 用于监控文件系统的对象
    private static ConcurrentQueue<FileChangeEvent> _changeQueue = new ConcurrentQueue<FileChangeEvent>(); // 线程安全的队列,用于存储文件变化事件
    private static CancellationTokenSource _cts = new CancellationTokenSource(); // 用于取消异步任务的令牌源
    private static string _logFilePath = "file_changes.log"; // 记录日志的文件路径

    static async Task Main(string[] args)
    {
        // 从配置文件读取监控目录和过滤规则
        string directoryToWatch = GetConfigValue("DirectoryToWatch", @"C:\Path\To\Directory");
        string filter = GetConfigValue("Filter", "*.*");

        // 创建FileSystemWatcher实例并配置
        _fileSystemWatcher = new FileSystemWatcher(directoryToWatch)
        {
            NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
            Filter = filter,
            IncludeSubdirectories = true
        };

        // 订阅事件
        _fileSystemWatcher.Created += OnChanged;
        _fileSystemWatcher.Changed += OnChanged;
        _fileSystemWatcher.Deleted += OnChanged;
        _fileSystemWatcher.Renamed += OnRenamed;

        // 开始监视
        _fileSystemWatcher.EnableRaisingEvents = true;

        // 启动异步任务来处理文件变化事件
        Task processingTask = Task.Run(() => ProcessFileChanges(_cts.Token));

        Console.WriteLine($"Monitoring changes to: {directoryToWatch}");
        Console.WriteLine("Press 'q' to quit the sample.");

        // 等待用户输入以结束程序
        while (Console.Read() != 'q') ;

        // 取消处理任务并等待完成
        _cts.Cancel();
        await processingTask;
    }

    private static void OnChanged(object source, FileSystemEventArgs e)
    {
        // 将文件变化事件添加到队列
        _changeQueue.Enqueue(new FileChangeEvent
        {
            FilePath = e.FullPath,
            ChangeType = e.ChangeType,
            ChangeTime = DateTime.Now
        });
    }

    private static void OnRenamed(object source, RenamedEventArgs e)
    {
        // 将重命名事件添加到队列
        _changeQueue.Enqueue(new FileChangeEvent
        {
            FilePath = e.FullPath,
            ChangeType = WatcherChangeTypes.Renamed,
            ChangeTime = DateTime.Now
        });
    }

    private static async Task ProcessFileChanges(CancellationToken token)
    {
        // 持续处理队列中的文件变化事件
        while (!token.IsCancellationRequested)
        {
            if (_changeQueue.TryDequeue(out FileChangeEvent changeEvent))
            {
                // 处理并记录文件变化事件到日志
                await LogChangeEventAsync(changeEvent);
            }
            else
            {
                // 如果队列为空,稍作等待以减少CPU使用率
                await Task.Delay(100, token);
            }
        }
    }

    private static async Task LogChangeEventAsync(FileChangeEvent changeEvent)
    {
        // 异步记录文件变化事件到日志文件
        string logMessage = $"{changeEvent.ChangeTime}: {changeEvent.FilePath} - {changeEvent.ChangeType}";
        await File.AppendAllTextAsync(_logFilePath, logMessage + Environment.NewLine);
    }

    private static string GetConfigValue(string key, string defaultValue)
    {
        // 从配置文件或环境变量读取配置值
        // 这里简单地返回默认值,实际应用中可以读取真实的配置
        return defaultValue;
    }
}


http://www.kler.cn/news/282847.html

相关文章:

  • Apache RocketMQ 中文社区全新升级丨阿里云云原生 7 月产品月报
  • 解决IDEA 控制台中文乱码及无法输入中文
  • MacOS通过Docker部署MySQL数据库,以及Docker Desktop进行管理
  • C++ 快速输入的优化与缓冲区管理(竞赛必用)
  • 使用requests库发起post请求处理json的两种方式
  • ROS 2 Jazzy和QT组合开发教程
  • 音频PCM的能量dB计算
  • 一个符合软件开发工程师认知的思考框架简单了解下
  • 1899. 最满意的方案
  • 盛元广通高等级生物安全实验室管理系统2.0
  • 【私有云场景案例分享②】批量装包与冒烟测试的自动化实现
  • Linux——进程管理
  • 嵌入式Linux学习笔记-Linux基础操作
  • Elasticsearch 8.13.4 LocalDateTime类型转换问题
  • 使用seamless-scroll-v3 实现无缝滚动,自动轮播平滑的滚动效果
  • Linux系统——服务器长时间训练不间断指令(nohup的简单用法)
  • PsConvertToGuiThread函数调用前传
  • 力扣第二阶段Days34
  • AI在医学领域:GluFormer一种可泛化的连续血糖监测数据分析基础模型
  • 自动化任务工具 | zTasker v1.97.1 绿色版
  • [Hive]四、Hive On Tez
  • 私域流量升级下的新机遇——“开源 AI 智能名片S2B2C 商城小程序”与新兴技术的融合
  • ARM/Linux嵌入式面经(二七):韶音
  • Java LeetCode 练习
  • pmp证书为何会被骂?他真的就是个垃圾证书?
  • 鸿蒙HarmonyOS开发实战: 页面传值跳转
  • Linux CMake根据环境变量和编译选项,编译多模块
  • k8s集群搭建
  • 四个版本的双向链表(C++,C++ CLI, C#, Java)
  • 奇安信渗透测试岗位三面经验分享