Filesystem event handling / Filesystemwatcher und co

  • VB.NET

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von vrtz.

    Filesystem event handling / Filesystemwatcher und co

    Hallo,

    Ich habe eine lokale Synchronisation zweier Ordner geschrieben. Diese muss aber manuell ausgelöst werden. Nun möchte ich als zweiten Synchronisationsmechanismus eine live-Synchronisation implementieren, dieser Mechanismus soll auf events lauschen die die beiden Synchronisationsordner betreffen, zB file.modified, file.created, file.deleted und dann die äquivalente Operation ausführen, also auch im zweiten Ordner die selbe datei löschen, die datei erneuern (überkopieren / löschen und neu einfügen / ersetzen) oder rüberkopieren wenn sie im anderen fehlt. Welche Komponenten / welches Wissen benötige ich wenn ich so eine Art Eventlistener erstellen möchte? Hat jemand vielleicht Beispielcode in der Richtung?

    Gruß,
    vrtz
    Das sieht zwar relativ einfach aus, ist aber vom Ablauf her nicht ganz trivial.
    Am besten, Du schreibst mal ganz genau auf, was passieren soll, wenn ...
    Insbesondere so was:
    Was soll z.B. passieren, wenn (quasi) zeitgleich in einem Ordner eine Datei gelöscht wird und kommunizierende Datei im anderen Ordner geändert wird? Das ist insbesondere dann interessant, wenn die beiden Ordner auf verschiedenen Festplatten liegen.
    Wenn Dinge nur in einem Ordner passieren, ist alles trivial.
    ---
    Wenn simultane Änderungen nicht vorkommen können, schreib hin:
    Unter der Voraussetzung, dass simultane Änderungen nicht vorkommen können...
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ok,

    Also prinzipiell habe ich den Filesystemwatcher grundlegend schon zum Laufen bekommen.

    Dort überwacht er folgende events:

    VB.NET-Quellcode

    1. AddHandler watcher.Changed, AddressOf OnChanged AddHandler watcher.Created, AddressOf OnCreated AddHandler watcher.Deleted, AddressOf OnDeleted



    VB.NET-Quellcode

    1. Private Sub OnChanged(source As Object, e As FileSystemEventArgs) Upload(e.FullPath, remoteDir + "\" + e.Name)
    2. End Sub
    3. Private Sub OnCreated(source As Object, e As FileSystemEventArgs)
    4. Upload(e.FullPath, remoteDir + "\" + e.Name)
    5. End Sub
    6. Private Sub OnDeleted(source As Object, e As FileSystemEventArgs)
    7. If File.Exists(remoteDir + "\" + e.Name) Then File.Delete(remoteDir + "\" + e.Name) End If
    8. End Sub



    Das bedeutet also das nach einer Änderung, also dem Abschließen eines Zugriffs mit Speichern der Daten die Datei rübergezogen wird, genauso dann wenn sie erstellt wurde. Wenn eine Datei im überwachten Ordner gelöscht wird, wird im zweiten Ordner geguckt ob sie dort auch vorhanden ist und dann ebenfalls gelöscht. Das ganze könnte ich jetzt noch für die Gegenseite machen wo auch nur auf diese 3 Events geguckt wird. Dann müsste ich auch noch Absicherungen einbauen, falls eine Datei die das Changed-Event auslöst bereits aus dem anderen Ordner kommt, also gerade synchronisiert wurde um endlos hin- und hersynchronisieren zu vermeiden. Ansonsten brauche ich mir keine große Gedanken machen, da die Synchronisierung ja erst stattfindet nachdem diese Events gelaufen sind. D.h. es kann gar keine Datei die gerade gelöscht wird rüber kopiert werden oder so.

    Jetzt würde ich gerne den ganzen FilesystemWatcher aber gerne asynchron im Hintergrund laufen lassen, damit ich die Live-Synchronisation beliebig an- und ausschalten kann. Problematisch wird es zB wenn keine Verbindung zwischen den beiden Ordnern besteht (getrenntes Medium o.ä.) dann könnte nicht repliziert werden und die Synchronität wäre dahin. Dafür wäre es auch interessant wie man solche Befehle in eine Art Queue stellen kann, die dann abgearbeitet wird, wenn die Verbindung wieder hergestellt wird.

    Abgesehen von dieser Live-Synchronisierung habe ich schon drei manuelle Synchronisierungsmechanismen (1. Vollsynchronisation, fehlende Dateien werden gegenseitig transferiert, es wird nichts gelöscht; 2. "LocalMasterSynchronisation": der zweite Ordner wird zur Kopie des ersten; 3. "RemoteMasterSynchronisation": Der erste Ordner wird zur Kopie des zweiten)fertig, die man auch einsetzen kann wenn die live-Synchronisation aus ist, abgeschaltet wurde oder die Replikation nicht hinbekommt, wegen was für einer Exception auch immer.

    Mein Ziel ist es nun sozusagen standardmäßig die Live-Replikation zum Laufen zu kriegen (im Hintergrund), die dadurch beendbar (für gar keine Synchronisation) oder pausierbar (Events werden gesammelt, Befehle in eine Queue gehängt und bei Bedarf dann abgearbeitet, es wird aber nicht direkt synchronisiert) ist, oder aber automatisch beendet wird, wenn man eine der drei manuellen Synchronisationen auslöst. Also soll immer maximal ein Synchronisationsmechanismus laufen oder halt keiner. Der User soll das über die GUI wählen können. Folglich müssten die manuelle Synchronisation auch im Background laufen.
    hmm, die Frage wäre ob der Filesystemwatcher gegenüber einem Synchronisations-Thread einen Vorteil bietet:
    Pro:
    - sehr zeitnahe Änderungen
    Kontra:
    - unzuverlässig beim Changed Event
    - häufig doppelte Events bei gleichem auslösendem Ereignis
    - Synchronsiationsproblem zweier konkurrierender asynchroner Vorgänge !

    Persönlich würde ich auf einen Thread ausweichen und diesen mit einem WaitHandle mit TimeOut schlafen legen. Der Thread kann dann
    - nach einer einstellbaren Maximalzeit aufwachen und arbeiten
    - manuell geweckt werden (Waithandle.Set)
    - wenn nötig sogar ein Hybrid, bei dem das WaitHandle an FSW Events gekoppelt wird ohne dass Mehrfachevents oder Synchronisationsprobleme auftreten

    warum Du Änderungen in eine Queue stecken und nacheinander abarbeiten möchtest ist mir unklar. Warum können Änderungen nicht anhand des Create/Change Date erledigt werden ?
    Danke für die Antwort,

    Ich werde mich mal schlau machen bezüglich WaitHandle und co. Die Unzuverlässigkeit des FileSystemWatchers war mir nicht bekannt.

    Die Queue ist eine Idee um die Live-Synchronisation funktionabel zu halten, auch wenn die Verbindung zwischen Ordner A und Ordner B abbricht, da ich bei der Live-Synchronisierung mir gedacht habe, einfach nur auf die Events zu lauschen und dann nur daran die Synchronisation zu machen, da ich mir dann die Komplettprüfung beider Ordner schenken kann und dann nur auf die Datei zugegriffen wird die gerade verändert wurde. Damit das funktioniert, muss ich das Event ja auch live abhandeln oder mir die Änderungen merken, die getroffen wurde und sie zu einem Zeitpunkt bearbeiten, andem Zugriff besteht.

    Hier einmal ein Modell zur Veranschaulichung:




    Kann sein das ich noch Prüfungen vergessen hab grad, aber so ungefähr ist mein Konzept beim Live-Sync, wie ich es mir ausgemalt habe. Ich habe das jetzt nur für die eine Seite gemalt, für die andere soll es aber im Prinzip genauso gelten (insofern das so funktioniert).

    Wichtig ist nun für mich, wie ich die Überwachung stabil mache, sodass Dateien nicht doppelt kopiert werden und wie ich die Überwachung so verstaue, dass sie performant ist, also keine anderen Anwendungen beeinträchtigt und sauber über mein Programm gestoppt werden kann um manuell zu synchronisieren (oder gar nicht). Problem ist das ich mit Multithreading auf Programmierebene keine Erfahrung habe und deswegen nicht weiß, welches Verfahren möglichst einfach, sauber und schnell ist.

    Gruß