在 C# 中,如果你想 监控文件的创建,并确保文件完全写入完成后再处理,单纯用 FileSystemWatcher 监听 Created 事件是不够的,因为 Created 触发时文件可能还在写入中,直接打开可能报错或读取不完整。

下面我给你一个完整的思路和示例:


1️⃣ 使用 FileSystemWatcher 监听文件创建

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string folderPath = @"C:\Temp";

        FileSystemWatcher watcher = new FileSystemWatcher(folderPath);
        watcher.Filter = "*.txt";        // 监控特定文件类型
        watcher.Created += OnCreated;
        watcher.EnableRaisingEvents = true;

        Console.WriteLine("监控开始,按回车退出...");
        Console.ReadLine();
    }

    private static void OnCreated(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"检测到文件创建: {e.FullPath}");
        // 延迟处理
        ProcessFileWhenReady(e.FullPath);
    }
}


2️⃣ 检查文件是否可用

因为 Created 事件触发时文件可能仍被写入,我们可以尝试打开文件直到成功:

private static void ProcessFileWhenReady(string filePath)
{
    const int maxRetries = 10;
    const int delayMs = 500;

    for (int i = 0; i < maxRetries; i++)
    {
        try
        {
            // 尝试以只读方式打开文件
            using (FileStream stream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.None))
            {
                Console.WriteLine($"文件准备就绪: {filePath}");
                // 在这里处理文件
                string content = File.ReadAllText(filePath);
                Console.WriteLine($"文件内容长度: {content.Length}");
                break; // 成功就退出循环
            }
        }
        catch (IOException)
        {
            // 文件被占用,等待一段时间再重试
            System.Threading.Thread.Sleep(delayMs);
        }
    }
}

✅ 原理

  1. File.Open(..., FileShare.None) 尝试独占文件。
  2. 如果文件正在写入,会抛出 IOException
  3. 捕获异常后等待一段时间再重试,直到文件写入完成。

3️⃣ 可优化方式

  • 异步处理:使用 Task.Run 避免阻塞事件线程。
  • 文件大小判断:连续两次文件大小相同再处理,也可以判断文件是否完成写入。
private static async Task ProcessFileWhenReadyAsync(string filePath)
{
    long lastSize = -1;
    while (true)
    {
        var info = new FileInfo(filePath);
        if (info.Length > 0 && info.Length == lastSize)
            break;

        lastSize = info.Length;
        await Task.Delay(500);
    }

    // 文件完成写入
    string content = await File.ReadAllTextAsync(filePath);
    Console.WriteLine($"文件完成写入, 长度: {content.Length}");
}


4️⃣ 总结

  1. FileSystemWatcher 捕获文件创建事件。
  2. 文件可能未写完,直接处理会失败。
  3. 通过:
    • 独占打开文件尝试,或
    • 判断文件大小稳定
      等方法,确保文件完成写入后再处理。
  4. 可结合异步方式提高性能和响应速度。