Verwenden von FileSystemWatcher zum Überwachen eines Verzeichnisses


101

Ich verwende eine Windows Forms-Anwendung, um ein Verzeichnis zu überwachen und die darin abgelegten Dateien in ein anderes Verzeichnis zu verschieben.

Im Moment wird die Datei in ein anderes Verzeichnis kopiert, aber wenn eine andere Datei hinzugefügt wird, endet sie einfach ohne Fehlermeldung. Manchmal werden zwei Dateien kopiert, bevor die dritte endet.

Liegt das daran, dass ich eine Windows Form-Anwendung anstelle einer Konsolenanwendung verwende? Gibt es eine Möglichkeit, das Beenden des Programms zu stoppen und das Verzeichnis weiter zu überwachen?

private void watch()
{
  this.watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  watcher.Filter = "*.*";
  watcher.Changed += OnChanged;
  watcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
  //Copies file to another directory.
}

public void Dispose()
{
  // avoiding resource leak
  watcher.Changed -= OnChanged;
  this.watcher.Dispose();
}

Antworten:


144

Das Problem waren die Benachrichtigungsfilter. Das Programm hat versucht, eine Datei zu öffnen, die noch kopiert wurde. Ich habe alle Benachrichtigungsfilter außer LastWrite entfernt.

private void watch()
{
  FileSystemWatcher watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastWrite;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

6
Hallo, ich habe diesen Ansatz verwendet, aber wenn ich eine Datei kopiere, wird das Ereignis zweimal ausgelöst: einmal, wenn die Datei leer erstellt wird (der Kopiervorgang beginnt) und ein weiteres Mal, wenn der Kopiervorgang abgeschlossen ist. Wie kann dieses doppelte Ereignis vermieden werden, wenn ein Filter in der Lage ist, es ohne eine benutzerdefinierte Steuerung zu verarbeiten?
dhalfageme

@dhalfageme Ich überprüfe beide Ereignisse, ob im Ordner etwas für meine Anwendung Bedeutendes angezeigt wird.
Eftekhari

30

Sie haben den Code für die Dateibehandlung nicht angegeben, aber ich gehe davon aus, dass Sie beim ersten Schreiben des gleichen Fehlers den gleichen Fehler gemacht haben: Das Filewatcher-Ereignis wird ausgelöst, sobald die Datei erstellt wird. Es wird jedoch einige Zeit dauern, bis die Datei fertig ist. Nehmen Sie zum Beispiel eine Dateigröße von 1 GB. Die Datei wird möglicherweise von einem anderen Programm erstellt (Explorer.exe kopiert sie von irgendwoher), aber es dauert Minuten, bis dieser Vorgang abgeschlossen ist. Das Ereignis wird zur Erstellungszeit ausgelöst und Sie müssen warten, bis die Datei zum Kopieren bereit ist.

Sie können warten, bis eine Datei fertig ist, indem Sie diese Funktion in einer Schleife verwenden.


25

Der Grund kann sein, dass Watcher als lokale Variable für eine Methode deklariert wird und nach Abschluss der Methode Müll gesammelt wird. Sie sollten es als Klassenmitglied deklarieren. Versuche Folgendes:

FileSystemWatcher watcher;

private void watch()
{
  watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
                         | NotifyFilters.FileName | NotifyFilters.DirectoryName;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
  //Copies file to another directory.
}

18
watcherDie Variable wird am Leben erhalten (kein gesammelter Müll), da er das geänderte Ereignis abonniert hat.
Adospace

1
Ich glaube, das liegt tatsächlich daran, dass EnableRaisingEvents auf eingestellt ist true. Ich glaube nicht, dass der Status von Event-Handlern für Mitglieder mit der Speicherbereinigung zu tun hat. Ich denke, EnableRaisingEvents hat, wie ich es nennen könnte, in diesem Fall ein besonderes Verhalten.
Matias Grioni
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.