Announcement

Collapse
No announcement yet.

Grundsätzliches zum FileSystemWatcher

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Grundsätzliches zum FileSystemWatcher

    Hallo zusammen,
    ich benötige mal nen paar Tipps zum FileSystemWatcher.

    Was ich mir vorstelle:
    Ich habe eine WinForm. In der befindet sich eine ListBox. Ich habe einen Ordner, welchen ich mit dem FileSystemWatcher überwachen möchte. Es sollen alle Unterverzeichnisse mit deren Dateien überwacht werden.

    Ich möchte immer den aktuellen Stand der im Ordner befindlichen Dateien in der Listbox angezeigt bekommen.

    Das soll dann in der ListBox in etwa so aussehen:
    C:\Test\Test1.txt
    C:\Test\Test2.txt
    C:\Test\Testen\Test1.txt

    usw.

    Meine Überlegung:
    Ich habe eine Function Names FindFiles erstellt in der ich den Inhalt des Ordners rekursiv mit den SubOrdner ermittle.

    Im FormLoad starte ich die Function FindFiles und weise das Ergebnis der Listbox zu. Dann starte ich den FileSystemWatcher. Bei Change, Delete oder Rename löse ich wiederum die Function FindFiles aus , lösche den bisherigen Inhalt der ListBox und weise das neue Ergebnis der ListBox zu.

    Macht das so Sinn, oder geht man da ganz anders heran ? Wie ?

    Schon mal Danke für euer Bemühen....

  • #2
    Hallo,

    Ich habe eine Function Names FindFiles erstellt in der ich den Inhalt des Ordners rekursiv mit den SubOrdner ermittle.
    Wird von .net auch angeboten
    Code:
    string[] files = Directory.GetFiles(basePath, "*", SearchOption.AllDirectories);
    Du kannst es entweder so mache wie du beschriebe hast: D.h. wenn eine Änderung vorliegt -> neu einlesen

    Oder du speicherst die Dateien die beim Start der Anwendung ermittelt werden in einem Dictionary und bindest dieses an die ListBox. Bei Änderungen werden nur die jeweiligen Werte aktualisiert.

    Welche Möglichkeit verwendet wird hängt auch davon ab wie viele Dateien überwacht werden sollen. Sind es viele wäre die zweite Möglichkeit effizienter.

    mfG Gü
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

    Comment


    • #3
      string[] files = Directory.GetFiles(basePath, "*", SearchOption.AllDirectories);
      das kannte ich noch gar nicht, muss ich mal ausprobieren.

      Da ich im Moment noch nicht abschätzen kann um wieviel Dateien es sich handeln wird, will ich mal vom schlimmsten Fall ausgehen...

      Oder du speicherst die Dateien die beim Start der Anwendung ermittelt werden in einem Dictionary und bindest dieses an die ListBox. Bei Änderungen werden nur die jeweiligen Werte aktualisiert.
      Dictionary - da musst du mir mal auf die Sprünge helfen, wie fange ich so etwas an..?

      Comment


      • #4
        Macht das so Sinn, oder geht man da ganz anders heran ? Wie ?
        Kommt drauf an
        Eigentlich kann man es so machen oder so wie Gü sagt nur die Änderungen nachziehen. Du solltest dir aber nochmal überlegen ob du den FileSystemWatcher überhaupt brauchst. Das Ding ist keine AllwaysWorkingRundumGlücklich-Komponente. Heißt es gibt keine Zusicherung das die jede Änderung mitbekommt und meldet (funktioniert eigentlich nur in einem lokalen NTFS Filesystem halbwegs vernünftig) oder das du bei einer Operation nur einen Event bekommst. Gerade beim kopieren oder moven von Files bekommst du einen Schwall von (eventuell nicht vollständigen) Events. Das Verhalten ist dabei auch noch je OS unterschiedlich!

        Wenn du eine kleine zu überprüfende Menge hast würde ich auf den FileSystemWatcher verzichten und selber das Verzeichnis regelmäßig über ein simples PollingSystem überprüfen.

        Comment


        • #5
          Code:
          string[] files = Directory.GetFiles(basePath, "*", SearchOption.AllDirectories);
          das kannte ich noch gar nicht, muss ich mal ausprobieren.
          SearchOption.AllDirectories ist mit Vorsicht zu genießen. Sobald du auf eine Datei/Verzeichnis stößt die du nicht, wegen fehlender Rechte, scannen darfst bricht GetFiles ab. Das Verhalten läßt sich leider auch nicht ändern, also so das man nur die Dateien bekommt für die man die nötigen Rechte hat.
          Die Rekursion über Subverzeichnisse sollte man daher sicherheitshalber lieber selbst übernehmen.

          Comment


          • #6
            Kann einfach über Timer gelöst werden.

            Das mit dem Dictionary (HashTable) war nur so eine Idee

            [highlight=vbnet]
            Imports System
            Imports System.IO
            Imports System.Windows.Forms

            Namespace WindowsFormsApplication1
            Public Partial Class Form1
            Inherits Form
            Private _files As String()
            Private _folder2Watch As String = Application.StartupPath

            Public Sub New()
            InitializeComponent()
            End Sub

            Private Sub timer1_Tick(ByVal sender As Object, ByVal e As EventArgs)
            _files = Directory.GetFiles(_folder2Watch, "*", SearchOption.AllDirectories)

            listBox1.DataSource = _files
            End Sub

            Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs)
            timer1.Start()
            End Sub

            Private Sub button2_Click(ByVal sender As Object, ByVal e As EventArgs)
            timer1.[Stop]()
            End Sub
            End Class
            End Namespace
            [/highlight]

            Hier ist noch GetFiles enthalten. Kann aber durch eigenen Code überschrieben werden.

            Ich finde es schade dass MS keine weitere Enum zum Steuern des Verhalten anbietet.

            mfG Gü
            "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

            Comment


            • #7
              Wenn du eine kleine zu überprüfende Menge hast würde ich auf den FileSystemWatcher verzichten und selber das Verzeichnis regelmäßig über ein simples PollingSystem überprüfen.
              Ihr sprecht immer von kleiner Datenmenge. Ab welcher Anzahl von Dateien und Verzeichnissen sprecht ihr von groß bzw klein...?

              Comment


              • #8
                Quantitative Angaben gibts nicht sondern nur qualitativer Natur.

                Werden immer alle Dateien bzw. deren Namen ermittelt werden alle Einträge in der Tabelle des NTFS (MFT - Master File Table) durchlaufen. Beim FileSystemWatcher wird jedoch nur die Änderung zurückgegeben.

                Somit ergibt sich ab einer bestimmten Anzahl ein Leistungsvorteil für den FSW. Dieser "Break Even Point" ist natürlich abhängig vom System, etc.

                Um es aber exemplarisch zu verdeutlichen würde ich sagen aber 10E6 Dateien ist der FSW besser.

                mfG Gü
                "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                Comment


                • #9
                  Code:
                  Um es aber exemplarisch zu verdeutlichen würde ich sagen aber 10E6 Dateien ist der FSW besser.
                  OK. Da komm ich mit Sicherheit nicht dran.

                  Dann wäre also die Timervariante und jedesmal den Gesamten Ordner auszulesen, die bessere Variante...

                  Comment


                  • #10
                    Ja, würde ich auch so machen.

                    mfG Gü
                    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                    Comment


                    • #11
                      Eine Frage habe ich doch noch...

                      Sehe ich das richti ?

                      Wenn ich die Function über einen Timer anstosse muss ich doch explizit ( evtl. über ein Flag ) abfangen, ob ich das Auslesen der Ordner und zuweisen der Werte an die ListBox abgeschlossen habe, bevor ich den nächsten Timer starte....


                      ..wenn ich die Function aber über den FileSysetmWatcher anstosse brauch ich das nicht, da diese die noch nicht abgeschlossenen änderungen in einen Speicher schreibt...


                      oder habe ich da einen Denkfehler...???

                      Comment


                      • #12
                        Probiers mit einem Test aus. ZB so
                        [highlight=vbnet]
                        Imports System
                        Imports System.Threading
                        Imports System.Windows.Forms

                        Namespace WindowsFormsApplication1
                        Public Partial Class Form1
                        Inherits Form
                        Public Sub New()
                        InitializeComponent()
                        End Sub

                        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
                        timer1.Interval = 100
                        timer1.Start()
                        End Sub

                        Private Sub timer1_Tick(ByVal sender As Object, ByVal e As EventArgs)
                        listBox1.Items.Add(Guid.NewGuid())

                        ' Länger warten als das Intervall ist:
                        Thread.Sleep(1000)
                        End Sub
                        End Class
                        End Namespace
                        [/highlight]

                        Anmerkung: Die Timer-Komponenten arbeitet im gleichen Thread wie der restliche Code der Form.

                        mfG Gü
                        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                        Comment


                        • #13
                          OK.
                          Das geht in diesem Fall

                          Aber bewirkt ein sleep nicht etwas anderes, als ob ich gerade eine Function abarbeite, und dann die "Liste" der ListBox übergebe..

                          z.B.
                          Ich starte die function
                          Die schaft es nicht im Interval fertig zu werden
                          Die nächste Function wird ausgelöst
                          Die würde es wieder nicht schaffen..

                          Was passiert dann....

                          Ein Sleep hat halt ganz andere Prio

                          Comment


                          • #14
                            mit einem Test aus. ZB
                            Sleep hab ich im Beispiel - das ist ein Test ohne im Produktivsystem verwendet zu werden - nur deshalb verwendet um einfach eine längere Operation bzw. Blockade des Threads zu simulieren die länger dauert als das Intervall des Timers.

                            mfG Gü
                            "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                            Comment

                            Working...
                            X