10 Stimmen

FileSystemWatcher-Trigger für Filestream open

Ich habe einen Filesystemwatcher, der ein Ereignis auslöst, wenn eine Datei geändert wird. Ich möchte aus dieser Datei lesen, sobald die Sperre aufgehoben wurde. Im Moment versuche ich nur, die Datei zu öffnen, sobald das Ereignis ausgelöst wird. Wenn eine große Datei kopiert wird, bleibt die Dateisperre für eine Weile bestehen, nachdem die Ereignisse gesendet wurden, und verhindert, dass die Datei für den Lesezugriff geöffnet wird.

Irgendwelche Vorschläge?

6voto

Aaronaught Punkte 118136

Dieses Problem ist tatsächlich ein bisschen schwierig, es sei denn, der Problembereich hat sich erheblich verändert, seit ich das letzte Mal damit zu tun hatte.

Am einfachsten ist es, einfach zu versuchen, die Datei zu öffnen, das Ergebnis abzufangen IOException und wenn die Datei gesperrt ist, wird sie in eine Warteschlange gestellt, um später überprüft zu werden. Sie können nicht einfach versuchen, jede eingehende Datei zu verarbeiten, denn es gibt alle möglichen Fälle, in denen mehrere Ereignisse für dieselbe Datei erzeugt werden. Stattdessen müssen Sie sie in eine Warteschlange einreihen und diese in regelmäßigen Abständen überprüfen.

Hier ist eine grundlegende Klassenvorlage, die Ihnen bei diesem Problem helfen sollte:

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);
        }
    }
}

(Hinweis: Ich habe das hier aus dem Gedächtnis abgerufen, es könnte also nicht perfekt sein - lassen Sie mich wissen, wenn es fehlerhaft ist).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X