使用文件观察器删除文件,不允许我第二次删除

时间:2015-12-17 13:08:30

标签: c# .net file console file-watcher

我的任务是在处理完成后删除文件。我正在使用FileWatcher来完成此任务。它正在观看特定文件夹。假设如果我复制一个文件并将其放在filewatcher文件夹中则删除。第二次我复制相同的文件并将其粘贴到同一个观看文件夹中。这次它说另一个进程正在使用该文件。抛出异常。我想我错过了一些东西。这是我的代码

private static void Main(string[] args)
    {

       var fw = new FileSystemWatcher(EmailSetting.DataFolder)
        {
            IncludeSubdirectories = false
            ,
            EnableRaisingEvents = true

        };
        fw.Created += (sender, e) =>
        {
         File.Delete(e.FullPath);

        };
        Console.ReadLine();
    }

1 个答案:

答案 0 :(得分:1)

创建文件时会收到Created事件(因此名称)。但是在这个时候,实际创建它的另一个进程没有完成将内容写入该文件。所以该文件可能已经存在,但另一个仍在使用它(想象你会复制一个8 GB的文件)。

将文件的路径简单地写入事件中的列表并让另一个线程定期检查此并发包(例如每秒一次)会更明智。首先,它检查文件是否存在,如果是,请尝试删除它。如果成功,请将其从包中取出,否则请在下次再试。

代码示例

private static readonly ConcurrentQueue<FileInfo> _FileCandidates = new ConcurrentQueue<FileInfo>();

private static void Main(string[] args)
{
    var watcher = new FileSystemWatcher
    {
        Path = @"R:\TestFolder",
        IncludeSubdirectories = false,
        Filter = "*.*",
    };

    Console.WriteLine("Start watching folder... " + watcher.Path);
    watcher.Created += OnFileCreated;
    watcher.EnableRaisingEvents = true;

    var timer = new Timer
    {
        AutoReset = true,
        Interval = 1000,
    };

    timer.Elapsed += OnTimerElapsed;
    timer.Enabled = true;

    Console.ReadKey();
}

static void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
    FileInfo file;
    var stillInUseFiles = new List<FileInfo>();

    Console.WriteLine("Check for file candidates...");
    while (_FileCandidates.TryDequeue(out file))
    {
        try
        {
            Console.WriteLine("Delete " + file.FullName);

            if (file.Exists)
                file.Delete();
        }
        catch (IOException)
        {
            Console.WriteLine("Could not delete file, try again next time.");
            stillInUseFiles.Add(file);
        }
    }

    foreach (var unhappyFile in stillInUseFiles)
    {
        _FileCandidates.Enqueue(unhappyFile);
    }
}

static void OnFileCreated(object sender, FileSystemEventArgs e)
{
    Console.WriteLine("Found new file candidate " + e.FullPath);
    _FileCandidates.Enqueue(new FileInfo(e.FullPath));
}