FileSystemWatcher vs Polling, um nach Dateiänderungen zu suchen

152

Ich muss eine Anwendung einrichten, die nach Dateien sucht, die in einem Verzeichnis sowohl lokal als auch auf einem Netzwerklaufwerk erstellt werden.

Wäre die FileSystemWatcheroder Abfrage auf einem Timer die beste Option. Ich habe beide Methoden in der Vergangenheit verwendet, aber nicht ausgiebig.

Welche Probleme (Leistung, Zuverlässigkeit usw.) gibt es bei beiden Methoden?

Jon Tackabury
quelle
3
FileSystemWatcher ist eine undichte Abstraktion und kann nur für die grundlegendsten Fälle verwendet werden. Siehe hier: stackoverflow.com/a/22768610/129130
Stein Åsmul
1
Möchten Sie einen Link für Verweis auf hinzuzufügen diese Antwort von Raymond Chen (Microsoft - Experten) zum Thema Filesystemwatcher Zuverlässigkeit . Und sein Blog: The Old New Thing (zum Beispiel nach FileSystemWatcher suchen).
Stein Åsmul

Antworten:

105

Ich habe gesehen, dass der Dateisystem-Watcher in Produktions- und Testumgebungen ausfällt. Ich halte es jetzt für eine Annehmlichkeit, aber ich halte es nicht für zuverlässig. Mein Muster war es, mit dem Dateisystem-Watcher nach Änderungen zu suchen, aber gelegentlich nach fehlenden Dateiänderungen zu suchen.

Bearbeiten: Wenn Sie eine Benutzeroberfläche haben, können Sie Ihrem Benutzer auch die Möglichkeit geben, Änderungen zu "aktualisieren", anstatt sie abzufragen. Ich würde dies mit einem Dateisystem-Watcher kombinieren.

Jason Jackson
quelle
11
Ich habe gesehen, ob ich auch runterfalle. Die Lösung, die wir verwendet haben, besteht darin, unsere eigene Klasse herumzuwickeln, wobei die Wrapper-Klasse AUCH einen Timer verwendet, um gelegentlich zu überprüfen, ob der Beobachter noch aktiv ist.
Joel Coehoorn
Wir machen etwas Ähnliches - sobald wir die an das FileCreated-Ereignis übergebene Datei verarbeitet haben, führen wir vor der Rückkehr eine manuelle Überprüfung auf andere neue Dateien durch. Dies scheint alle Probleme zu mindern, die auftreten, wenn viele Dateien gleichzeitig eintreffen.
John Sibly
4
Ich glaube, wir haben es in XP und Server 2003 in einem lokalen Verzeichnis und einer Dateifreigabe getestet und hatten XP-Computer im Feld. Wir hatten Probleme sowohl mit dem lokalen Verzeichnis als auch mit der Dateifreigabe. Eine der wahrscheinlichen Ursachen, die wir gefunden haben, war das Kopieren / Erstellen vieler Dateien in kurzer Zeit im Verzeichnis.
Jason Jackson
5
Es ist weder sehr konstruktiv noch professionell zu sagen "Ich habe eines Tages einen Geist gesehen". Es scheint, dass Leute im Thread, die das msdn-Dokument über nicht seitenauslauffähige Pufferüberläufe erwähnen, Ihre Probleme erklären könnten. Haben Sie versucht, Brents Ansatz zu verwenden?
v.oddou
4
Ich habe gerade einen Gassensor bei Amazon gekauft und es hat mich erstaunt, wie viele Leute sagten, dass er nicht funktioniert, wenn sie ihn offensichtlich nicht richtig kalibriert haben oder nicht einmal über die Kalibrierung Bescheid wissen ... FileSystemWatcher hat Einschränkungen mit hohem Datenverkehr von seine Puffergröße. Fast garantiert, dass dies der Grund für das "Scheitern" ist. Dies wird in der Dokumentation leicht erklärt, und es gibt Problemumgehungen, die einen sehr zuverlässigen Betrieb ermöglichen (siehe unten). Dies ist keine gute Antwort, um nur zu sagen: "Ähm, etwas hat dieses eine Mal nicht funktioniert, nicht sicher warum ... niemand sollte sich darauf verlassen."
U8it
60

Das größte Problem, das ich hatte, ist das Fehlen von Dateien, wenn der Puffer voll ist. Einfach zu reparieren - erhöhen Sie einfach den Puffer. Denken Sie daran, dass es die Dateinamen und Ereignisse enthält. Erhöhen Sie es daher auf die erwartete Anzahl von Dateien (Versuch und Irrtum). Es wird Speicher verwendet, der nicht ausgelagert werden kann, sodass andere Prozesse möglicherweise zur Seite gezwungen werden, wenn der Speicher knapp wird.

Hier ist der MSDN-Artikel zum Puffer: FileSystemWatcher .. ::. InternalBufferSize-Eigenschaft

Pro MSDN:

Das Erhöhen der Puffergröße ist teuer, da es aus nicht ausgelagertem Speicher stammt, der nicht auf die Festplatte ausgelagert werden kann. Halten Sie den Puffer daher so klein wie möglich. Verwenden Sie die Eigenschaften NotifyFilter und IncludeSubdirectories, um unerwünschte Änderungsbenachrichtigungen herauszufiltern, um einen Pufferüberlauf zu vermeiden.

Wir verwenden 16 MB aufgrund einer großen Charge, die auf einmal erwartet wird. Funktioniert gut und verpasst nie eine Datei.

Wir lesen auch alle Dateien, bevor wir anfangen, auch nur eine zu verarbeiten. Lassen Sie die Dateinamen sicher zwischengespeichert (in unserem Fall in eine Datenbanktabelle) und verarbeiten Sie sie dann.

Bei Problemen mit der Dateisperrung starte ich einen Prozess, der darauf wartet, dass die Datei entsperrt wird, und eine Sekunde, dann zwei, dann vier usw. wartet. Wir wählen nie ab. Dieser ist seit etwa zwei Jahren fehlerfrei in Produktion.


quelle
12
Pufferüberlauf? Oh, du meinst Stapelüberlauf.
TheFlash
1
Ab .NET 3.5: "Sie können den Puffer auf 4 KB oder mehr einstellen, er darf jedoch 64 KB nicht überschreiten"
Brad
9
Wie verwenden Sie 16 MB, wenn der maximale interne Puffer für FileSystemWatcher 64 KB beträgt?
BK
1
@ Jarvis, ein Puffer ist ein temperierter Speicherort, der so konfiguriert ist, dass er Informationen während der Übertragung speichert, bis sie verarbeitet werden können. Dies bedeutet normalerweise ein FIFO oder eine Warteschlange, da Sie Anforderungen in der Reihenfolge bearbeiten möchten, in der sie ankommen, jedoch in einigen Prozessen wie der Rekursion in Programmen Eine FILO- oder Stapelstruktur wird verwendet. In diesem Fall beziehen wir uns definitiv auf den Ereigniswarteschlangenpuffer und nicht auf den Programmaufrufstapelpuffer
MikeT
1
petermeinl.wordpress.com/2015/05/18/tamed-filesystemwatcher In diesem Beitrag werden robuste Wrapper für die Standardprobleme des FileSystemWatcher (FSW) beschrieben, die häufig bei der Überwachung des Dateisystems in realen Anwendungen auftreten.
Kiquenet
35

Das FileSystemWatcherkann auch Änderungen während der Stoßzeiten übersehen, wenn die Anzahl der Änderungen in der Warteschlange den bereitgestellten Puffer überläuft. Dies ist keine Einschränkung der .NET-Klasse an sich, sondern der zugrunde liegenden Win32-Infrastruktur. Nach unserer Erfahrung besteht der beste Weg, um dieses Problem zu minimieren, darin, die Benachrichtigungen so schnell wie möglich aus der Warteschlange zu entfernen und sie in einem anderen Thread zu bearbeiten.

Wie oben von @ChillTemp erwähnt, funktioniert der Watcher möglicherweise nicht mit Nicht-Windows-Freigaben. Beispielsweise funktioniert es auf gemounteten Novell-Laufwerken überhaupt nicht.

Ich bin damit einverstanden, dass ein guter Kompromiss darin besteht, gelegentlich eine Umfrage durchzuführen, um verpasste Änderungen festzustellen.

Brent Rockwood
quelle
4
Der Dateisystem-Watcher kann schnell hintereinander viele Ereignisse auslösen. Wenn Sie Ihren Event-Handler nicht mindestens so schnell ausführen können, wie er ausgelöst wird, wird der Handler schließlich Ereignisse auf den Boden werfen und Sie werden Dinge verpassen.
Brent Rockwood
17

Beachten Sie auch, dass der Dateisystem-Watcher auf Dateifreigaben nicht zuverlässig ist. Insbesondere, wenn die Dateifreigabe auf einem Nicht-Windows-Server gehostet wird. FSW sollte nicht für kritische Zwecke verwendet werden. Oder sollte mit einer gelegentlichen Umfrage verwendet werden, um zu überprüfen, ob nichts übersehen wurde.

chilltemp
quelle
3
Hat Microsoft bestätigt, dass es auf Nicht-Windows-Dateifreigaben nicht zuverlässig ist? Wir erleben dies sicherlich aus erster Hand, seit wir von einer Windows-Freigabe zu einer Linux-basierten SMB-Freigabe gewechselt sind.
Sean
1
Nicht dass ich wüsste. Und ich bin mir sicher, dass es einfach ein Schuldspiel zwischen den verschiedenen Anbietern sein würde.
Chilltemp
1
Wir haben Probleme mit dem Dateisystem-Watcher auf zugeordneten Laufwerken festgestellt. Wenn die Karte getrennt und dann wieder verbunden wird, werden vom Datei-Watcher keine Änderungen mehr vorgenommen. Leicht gelöst, aber immer noch ein Streik gegen den Dateisystem-Beobachter IMHO.
Richard Dorman
11

Persönlich habe ich das FileSystemWatcherauf einem Produktionssystem verwendet, und es hat gut funktioniert. In den letzten 6 Monaten gab es keinen einzigen Schluckauf, der rund um die Uhr lief. Es überwacht einen einzelnen lokalen Ordner (der gemeinsam genutzt wird). Wir haben eine relativ kleine Anzahl von Dateioperationen, die verarbeitet werden müssen (10 Ereignisse pro Tag). Ich musste mir nie Sorgen machen. Ich würde es wieder benutzen, wenn ich die Entscheidung neu treffen müsste.

Jim
quelle
7

Ich verwende derzeit die FileSystemWatcherXML-Datei, die durchschnittlich alle 100 Millisekunden aktualisiert wird.

Ich habe festgestellt, dass FileSystemWatcherSie niemals Probleme mit lokalen Dateien haben sollten , solange das richtig konfiguriert ist .

Ich habe keine Erfahrung mit Remote-Dateiüberwachung und Nicht-Windows-Freigaben.

Ich würde das Abrufen der Datei als redundant betrachten und den Overhead nicht wert sein, es sei denn, Sie misstrauen von Natur aus FileSystemWatcherden Einschränkungen, die alle anderen hier aufgeführt haben (Nicht-Windows-Freigaben und Remote-Dateiüberwachung).

PersistenceOfVision
quelle
5

Ich würde mit Umfragen gehen.

Netzwerkprobleme führen FileSystemWatcherdazu, dass das Ereignis unzuverlässig ist (selbst wenn das Fehlerereignis überlastet wird).

bläulich
quelle
5

Ich habe Probleme bei der Verwendung FileSystemWatcherauf Netzwerkfreigaben. Wenn Sie sich in einer reinen Windows-Umgebung befinden, ist dies möglicherweise kein Problem, aber ich habe eine NFS-Freigabe angesehen. Da NFS zustandslos ist, gab es keine Benachrichtigung, als sich die von mir beobachtete Datei änderte.

Jon Norton
quelle
Ich habe das gleiche Problem festgestellt, aber es war für mich unerwartet, da sich der FileSystemWatcher auf demselben Windows-Server befand, der den Ordner mithilfe von NFS freigibt. Die Tatsache, dass ein Ordner mit NFS freigegeben wird, führt dazu, dass der Dateisystemwatcher keine Dateien sieht, die mit der Freigabe remote erstellt wurden (dh von einem Linux, das die Freigabe zuordnet). Wenn ich eine Datei in denselben Ordner schreibe, der überwacht wird, wird der Dateisystemwatcher ausgelöst. Es sieht so aus, als ob der NFS-Server Dateien mit einer niedrigeren Ebene schreibt und die API-Ebene, die auslöst, dass der Dateisystemwatcher nicht aktiviert ist. Hat jemand weitere Informationen?
Mosè Bottacini
3

Ich hatte einige große Probleme mit FSW auf Netzwerklaufwerken: Das Löschen einer Datei löste immer das Fehlerereignis aus, niemals das gelöschte Ereignis. Ich habe keine Lösung gefunden, deshalb vermeide ich jetzt das FSW und verwende Polling.

Erstellungsereignisse hingegen funktionierten einwandfrei. Wenn Sie also nur auf die Dateierstellung achten müssen, können Sie sich für den FSW entscheiden.

Außerdem hatte ich überhaupt keine Probleme mit lokalen Ordnern, egal ob geteilt oder nicht.

Treb
quelle
3

Die schnellstmögliche Rückkehr von der Ereignismethode mithilfe eines anderen Threads löste das Problem für mich:

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    Task.Run(() => MySubmit(e.FullPath));
}
spludlow
quelle
2

Die Verwendung von FSW und Polling ist meiner Meinung nach eine Verschwendung von Zeit und Ressourcen, und ich bin überrascht, dass erfahrene Entwickler dies vorschlagen. Wenn Sie Polling verwenden müssen, um nach "FSW-Fehlern" zu suchen, können Sie FSW natürlich ganz verwerfen und nur Polling verwenden.

Ich versuche derzeit zu entscheiden, ob ich FSW oder Polling für ein von mir entwickeltes Projekt verwenden werde. Wenn Sie die Antworten lesen, ist es offensichtlich, dass es Fälle gibt, in denen FSW die Anforderungen perfekt abdeckt, während Sie in anderen Fällen Abfragen benötigen . Leider hat sich keine Antwort tatsächlich mit dem Leistungsunterschied (falls vorhanden) befasst , sondern nur mit den "Zuverlässigkeitsproblemen". Gibt es jemanden, der diesen Teil der Frage beantworten kann?

BEARBEITEN: Der Punkt von nmclean für die Gültigkeit der Verwendung von FSW und Polling (Sie können die Diskussion in den Kommentaren lesen, wenn Sie interessiert sind) scheint eine sehr rationale Erklärung zu sein, warum es Situationen geben kann, in denen sowohl FSW als auch Polling verwendet werden effizient. Vielen Dank, dass Sie das für mich (und alle anderen, die die gleiche Meinung haben) beleuchtet haben , nmclean .

ThunderGr
quelle
1
Was ist, wenn Sie so schnell wie möglich auf Dateiänderungen reagieren möchten? Wenn Sie beispielsweise einmal pro Minute abfragen, kann es sein, dass zwischen dem Ändern einer Datei und dem Aufnehmen der Änderung durch Ihre Anwendung eine Verzögerung von bis zu 1 Minute liegt. Das FSW-Ereignis würde vermutlich viel früher ausgelöst. Wenn Sie also beide verwenden, behandeln Sie die Ereignisse so schnell wie möglich, erfassen aber auch die verpassten Ereignisse, falls vorhanden.
Rom99
@ rom99 Genau mein Punkt. Wenn der FSW in Fällen, in denen Sie eine schnelle Antwort benötigen, unzuverlässig ist, macht es keinen Sinn, ihn zu verwenden, da Sie Fälle haben, in denen keine schnelle Antwort erfolgt, sodass Ihre Anwendung unzuverlässig ist. In kürzeren Abständen in einem Thread abzufragen, wäre das, was Sie tun müssen. Wenn Sie beides tun , haben Sie eine Toleranz für die Antwortzeiten, die von der Abfrage abgedeckt werden. Warum also nicht nur die Abfrage verwenden?
ThunderGr
5
@ThunderGr "Somit ist Ihre Bewerbung unzuverlässig." - In vielen Fällen ist Geschwindigkeit keine Voraussetzung für Zuverlässigkeit. Die Arbeit muss erledigt sein, aber es kann eine Weile warten. Wenn wir langsames, zuverlässiges Polling mit schnellem, unzuverlässigem FSW kombinieren , erhalten wir eine Anwendung, die immer zuverlässig und manchmal schnell ist, besser als zuverlässig und niemals schnell. Wir können FSW entfernen und die gleiche maximale Antwortzeit durch ständiges Abrufen erreichen. Dies geht jedoch zu Lasten der Reaktionsfähigkeit des Restes der Anwendung und sollte daher nur erfolgen, wenn eine sofortige Antwort unbedingt erforderlich ist.
nmclean
2
Nun , warum ist die über einem schlechten Argument? Denn obwohl wir immer noch Festplattenzugriff benötigen, brauchen wir ihn weniger . Ebenso können Sie weniger abfragen. Nur weil wir immer noch alle Dateien überprüfen, bedeutet dies nicht, dass die Arbeitslast gleich ist. Ihre Aussage "Abfrage ist mit FSW in der CPU-Zeit teuer oder nicht" ist falsch . Indem wir das Problem der "Unmittelbarkeit" an FSW auslagern, können wir die Abfrage in eine inaktive Aufgabe mit niedriger Priorität ändern , sodass die Geschäftigkeit der Anwendung zu einem bestimmten Zeitpunkt drastisch reduziert wird, während immer noch die "Unmittelbarkeit" behandelt wird. Mit Umfragen allein können Sie einfach nicht das gleiche Gleichgewicht erreichen.
nmclean
9
@nmclean Vielen Dank, dass Sie sich die Zeit und Energie genommen haben, dies so zu klären, wie Sie es getan haben. Wenn Sie es so ausdrücken, macht es sicherlich viel mehr Sinn. So wie es Zeiten gibt, in denen ein Cache nicht für Ihr spezifisches Problem geeignet ist, ist der FSW (wenn er sich als unzuverlässig erweist) möglicherweise nicht geeignet. Es stellt sich heraus, dass Sie die ganze Zeit Recht hatten. Es tut mir leid, dass ich so viel Zeit gebraucht habe, um es zu bekommen.
ThunderGr
1

Arbeitslösung für die Arbeit mit create event statt change

Auch zum Kopieren, Ausschneiden, Einfügen, Verschieben.

class Program
{        

        static void Main(string[] args)
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";
            FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
            FileSystemWatcher.Path = SourceFolderPath;
            FileSystemWatcher.IncludeSubdirectories = false;
            FileSystemWatcher.NotifyFilter = NotifyFilters.FileName;   // ON FILE NAME FILTER       
            FileSystemWatcher.Filter = "*.txt";         
             FileSystemWatcher.Created +=FileSystemWatcher_Created; // TRIGGERED ONLY FOR FILE GOT CREATED  BY COPY, CUT PASTE, MOVE  
            FileSystemWatcher.EnableRaisingEvents = true;

            Console.Read();
        }     

        static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {           
                string SourceFolderPath = "D:\\SourcePath";
                string DestinationFolderPath = "D:\\DestinationPath";

                try
                {
                    // DO SOMETING LIKE MOVE, COPY, ETC
                    File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
                }
                catch
                {
                }          
        }
}

Lösung für diesen Datei-Watcher beim Ändern des Dateiattributereignisses mithilfe statischen Speichers

class Program
{
    static string IsSameFile = string.Empty;  // USE STATIC FOR TRACKING

    static void Main(string[] args)
    {
         string SourceFolderPath = "D:\\SourcePath";
        string DestinationFolderPath = "D:\\DestinationPath";
        FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
        FileSystemWatcher.Path = SourceFolderPath;
        FileSystemWatcher.IncludeSubdirectories = false;
        FileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;          
        FileSystemWatcher.Filter = "*.txt";         
        FileSystemWatcher.Changed += FileSystemWatcher_Changed;
        FileSystemWatcher.EnableRaisingEvents = true;

        Console.Read();
    }     

    static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        if (e.Name == IsSameFile)  //SKIPS ON MULTIPLE TRIGGERS
        {
            return;
        }
        else
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";

            try
            {
                // DO SOMETING LIKE MOVE, COPY, ETC
                File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
            }
            catch
            {
            }
        }
        IsSameFile = e.Name;
    }
}

Dies ist eine Problemumgehungslösung für dieses Problem mehrerer auslösender Ereignisse.

Mark Macneil Bikeio
quelle
0

Ich würde sagen, verwenden Sie Polling, insbesondere in einem TDD-Szenario, da es viel einfacher ist, das Vorhandensein von Dateien zu verspotten / zu stubben oder auf andere Weise, wenn das Polling-Ereignis ausgelöst wird, als sich auf das "unkontrolliertere" fsw-Ereignis zu verlassen. + dazu, dass an einer Reihe von Apps gearbeitet wurde, die von fsw-Fehlern geplagt wurden.

user2819502
quelle