FileSystemWatcher запускает для открытия файлового потока - PullRequest
10 голосов
/ 09 февраля 2010

У меня есть файловая система, которая запускает событие при изменении файла. Я хочу прочитать из этого файла после снятия блокировки. В данный момент я просто пытаюсь открыть файл после запуска события, когда копируется большой файл, блокировка файла остается на некоторое время после отправки событий, предотвращая открытие файла для доступа на чтение.

Есть предложения?

1 Ответ

6 голосов
/ 09 февраля 2010

Это на самом деле немного глупо, если только проблемное пространство не сильно изменилось с тех пор, как мне в последний раз приходилось с ним сталкиваться.

Самый простой способ - просто попытаться открыть файл, поймать полученный IOException и, если файл заблокирован, добавить его в очередь для проверки позже. Вы не можете просто попытаться обработать каждый входящий файл, потому что есть разные случаи, когда для одного и того же файла будет сгенерировано несколько событий, поэтому настройка цикла повторения для каждого полученного события может быстро привести к катастрофе. Вместо этого вам нужно поставить их в очередь и регулярно проверять очередь.

Вот базовый шаблон класса, который должен помочь вам с этой проблемой:

public class FileMonitor : IDisposable
{
    private const int PollInterval = 5000;

    private FileSystemWatcher watcher;
    private HashSet<string> filesToProcess = new HashSet<string>();
    private Timer fileTimer;  // System.Threading.Timer

    public FileMonitor(string path)
    {
        if (path == null)
            throw new ArgumentNullException("path");

        watcher = new FileSystemWatcher();
        watcher.Path = path;
        watcher.NotifyFilter = NotifyFilters.FileName;
        watcher.Created += new FileSystemEventHandler(FileCreated);
        watcher.EnableRaisingEvents = true;

        fileTimer = new Timer(new TimerCallback(ProcessFilesTimer),
            null, PollInterval, Timeout.Infinite);
    }

    public void Dispose()
    {
        fileTimer.Dispose();
        watcher.Dispose();
    }

    private void FileCreated(object source, FileSystemEventArgs e)
    {
        lock (filesToProcess)
        {
            filesToProcess.Add(e.FullPath);
        }
    }

    private void ProcessFile(FileStream fs)
    {
        // Your code here...
    }

    private void ProcessFilesTimer(object state)
    {
        string[] currentFiles;
        lock (filesToProcess)
        {
            currentFiles = filesToProcess.ToArray();
        }
        foreach (string fileName in currentFiles)
        {
            TryProcessFile(fileName);
        }
        fileTimer.Change(PollInterval, Timeout.Infinite);
    }

    private void TryProcessFile(string fileName)
    {
        FileStream fs = null;
        try
        {
            FileInfo fi = new FileInfo(fileName);
            fs = fi.OpenRead();
        }
        catch (IOException)
        {
            // Possibly log this error
            return;
        }

        using (fs)
        {
            ProcessFile(fs);
        }

        lock (filesToProcess)
        {
            filesToProcess.Remove(fileName);
        }
    }
}

(Примечание. Я вспоминаю это по памяти, поэтому оно может быть не идеальным - дайте мне знать, если оно глючит.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...