You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FileSystemWatcher Deleted事件仅偶尔触发,测试30次仅10-15次生效求助

解决FileSystemWatcher Deleted事件触发不稳定的问题

我之前也碰到过FileSystemWatcher事件触发不规律的情况,结合你近30次测试只有10-15次触发的现象,主要是几个容易忽略的细节导致的,咱们一步步解决:

1. 确保FileSystemWatcher对象不被垃圾回收

如果你的fileSystemWatcher是局部变量(比如在某个方法内部声明),方法执行完毕后,.NET的垃圾回收器可能会把它回收掉,导致后续的文件操作无法触发事件。

解决方法:把fileSystemWatcher声明为类级别的字段,保持强引用:

// 类级别字段,避免被GC回收
private FileSystemWatcher _fileSystemWatcher;

public void SetupWatcher()
{
    string fileToWatchFor = "file.txt";
    var inputedFileInfo = new FileInfo(fileToWatchFor);
    _fileSystemWatcher = new FileSystemWatcher(inputedFileInfo.DirectoryName);
    _fileSystemWatcher.Filter = "*.txt";
    _fileSystemWatcher.Deleted += (sender, eventArgs) => 
    {
        Console.WriteLine("I was invoked when your file was deleted!");
    };
    // 其他配置...
}

2. 必须启用事件触发

FileSystemWatcher默认是关闭事件触发的,你需要手动设置EnableRaisingEvents = true,否则无论怎么操作文件,事件都不会被触发。这是最容易漏掉的一步!

添加这行代码:

_fileSystemWatcher.EnableRaisingEvents = true;

3. 增大内部缓冲区避免溢出

当短时间内有大量文件操作(或者你的测试操作太频繁),FileSystemWatcher的内部缓冲区可能会溢出,导致部分事件丢失。默认缓冲区大小比较小,你可以适当调大(最大支持64KB):

// 设置缓冲区为64KB(最大值)
_fileSystemWatcher.InternalBufferSize = 65536;

4. 额外:监听Renamed事件辅助判断

有些程序删除文件的逻辑是先重命名再删除,这种情况下Deleted事件可能不会触发,但Renamed事件会捕捉到。你可以同时监听Renamed事件,做补充判断:

_fileSystemWatcher.Renamed += (sender, eventArgs) =>
{
    // 可以判断是否是目标文件被重命名后删除的情况
    if (eventArgs.OldName == "file.txt")
    {
        Console.WriteLine("Target file was renamed (might be deleted afterwards)!");
    }
};

修正后的完整示例代码

using System;
using System.IO;

public class FileWatcherExample
{
    private FileSystemWatcher _fileSystemWatcher;

    public void StartWatching()
    {
        string fileToWatchFor = "file.txt";
        var inputedFileInfo = new FileInfo(fileToWatchFor);
        
        if (!inputedFileInfo.Directory.Exists)
        {
            Console.WriteLine("Target directory does not exist!");
            return;
        }

        _fileSystemWatcher = new FileSystemWatcher(inputedFileInfo.DirectoryName)
        {
            Filter = "*.txt",
            InternalBufferSize = 65536,
            EnableRaisingEvents = true
        };

        _fileSystemWatcher.Deleted += (sender, eventArgs) =>
        {
            Console.WriteLine($"I was invoked when {eventArgs.Name} was deleted!");
        };

        _fileSystemWatcher.Renamed += (sender, eventArgs) =>
        {
            if (eventArgs.OldName.Equals(fileToWatchFor, StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine($"Target file {fileToWatchFor} was renamed to {eventArgs.Name}");
            }
        };

        Console.WriteLine("Watching for .txt file deletions... Press any key to stop.");
        Console.ReadKey();
        
        // 停止监听并释放资源
        _fileSystemWatcher.EnableRaisingEvents = false;
        _fileSystemWatcher.Dispose();
    }
}

按照这个配置再测试,应该能大幅提升Deleted事件的触发成功率,基本可以做到每次删除都能捕捉到。

内容的提问来源于stack exchange,提问作者perepelart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:26:55