0

我的任务是在处理完成后删除文件。我正在使用 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();
    }
4

1 回答 1

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));
}
于 2015-12-17T13:30:00.380 回答