Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
FilesystemWatcher nur ein gefeuertes Event verwerten
Rioma
myCSharp.de - Member



Dabei seit:
Beiträge: 228

Themenstarter:

FilesystemWatcher nur ein gefeuertes Event verwerten

beantworten | zitieren | melden

Hallo zusammen,

ich habe ein kleines Problem mit dem Verhalten des FilesystemWatchers. Bekanntlich werden für eine Datei die Events häufig mehrfach gefeuert (Es geht nur um das OnCreated).

Ich würde das Event aber gerne nur einmal verarbeiten, bis die Datei wieder von mir "freigegeben" wurde.
Ich habe im Handler ein Hashset erstellt und füge den Pfad hinzu. Sollte das fehlschlagen, würde die eigentliche Aktion nicht ausgelöst werden.


 private HashSet<string> files = new HashSet<string>();

        private void FileCreated(object sender, FilePathEventArgs e)
        {
            try
            {
                if (files.Add(e.FilePath))
                   //aktion();
            }
            catch (Exception ex)
            {
//Test
            }

        }

Die Add Funktion ist natürlich nicht atomar und die Events werden so schnell gefeuert, das die Aktion dennoch 2 Mal ausgeführt wird.

Hat jemand eine andere Idee?

Danke
private Nachricht | Beiträge des Benutzers
Jamikus
myCSharp.de - Member



Dabei seit:
Beiträge: 244
Herkunft: Oberhausen (NRW)

beantworten | zitieren | melden

Event beim 1. Auslösen deabonnieren und beim "Freigeben" wieder abonnieren ist keine Option?
private Nachricht | Beiträge des Benutzers
Coffeebean
myCSharp.de - Team

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2.207
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

Hallo Rioma,

du könntest mit ner boolschen Variable abfragen, ob du das Event überhaupt ausführen sollst. Im finally setzt dus dann weider auf true. Das ist zwar nicht schön, aber vielleicht hilft es ja.

Grad gefunden:
Zitat von http://weblogs.asp.net/ashben/31773
1. Events being raised twice - An event will be raised twice if an event handler (AddHander FSW.Created, AddressOf FSW_Created) is explicitly specified. This is because, by default, the public events automatically call the respective protected methods (OnChanged, OnCreated, OnDeleted, OnRenamed). To correct this problem, simply remove the explicit event handler (AddHandler ...).

Gruss

Coffeebean
private Nachricht | Beiträge des Benutzers
Rioma
myCSharp.de - Member



Dabei seit:
Beiträge: 228

Themenstarter:

beantworten | zitieren | melden

Deabonnieren ist keine Option, da so potentielle andere Dateien übersehen werden.

Die Abfrage des booleschen Wertes müsste aber auf Dateiebene stattfinden. Da andere Dateien natürlich noch verarbeitet werden sollen. Ich denke ich werde hier ebenfalls das Problem haben, dass dies zu langsam ist.
Das Event habe ich nicht explizit abonniert.


 _fileSystemWatcher.Created += FileSystemWatcherOnCreated;

Ich denke mein Problem ist hier erklärt:

FileSystemWatcher Changed event is raised twice
private Nachricht | Beiträge des Benutzers
Coffeebean
myCSharp.de - Team

Avatar #avatar-3295.gif


Dabei seit:
Beiträge: 2.207
Herkunft: Deutschland/Schweiz

beantworten | zitieren | melden

Zitat von Rioma
Ich denke mein Problem ist hier erklärt:

Heisst das, du hast das Problem mit dem SO-Thread gelöst? Wenn ja: Wie? Oder heisst das nur, dass dies dein Problem noch besser beschreibt?

Gruss

Coffeebean
private Nachricht | Beiträge des Benutzers
Rioma
myCSharp.de - Member



Dabei seit:
Beiträge: 228

Themenstarter:

beantworten | zitieren | melden

Gelöst leider nicht. Ich wollte damit nur sagen, dass mein Problem nicht von den expliziten Eventhandlern kommt.

Absolut letzte Option wäre RX:


var watcher = new FileSystemWatcher("./");

Observable.FromEventPattern<FileSystemEventArgs>(watcher, "Changed")
            .Throttle(new TimeSpan(500000))
            .Subscribe(HandleChangeEvent);

watcher.EnableRaisingEvents = true;

Aber ich füge eine lib natürlich ungern für eine einzige Stelle hinzu.

Edit: Der Code ist aus dem Link
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Rioma am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.852

beantworten | zitieren | melden

Dein Wunsch ist so vom FSW nicht abgedeckt. Dass bei einem Create zwei Events gefeuert werden, ist nichts neues und by design
Ergo musst Du das selbst umsetzen.
private Nachricht | Beiträge des Benutzers
MATSE01
myCSharp.de - Member



Dabei seit:
Beiträge: 19
Herkunft: Hamburg

beantworten | zitieren | melden

Hast Du schon mal das Deleted Event angeschaut?
Wenn man zum Beispiel mit Notepad++ eine Datei speichert, passiert folgendes:

Created -> Deleted -> Created

Könnte man wie folgt abfangen:


        private static void watcher_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            var time = File.GetCreationTimeUtc(e.FullPath);
            long offset = 504911232000000000;
            if (offset == time.Ticks) return;
            Console.WriteLine("Created " + e.Name);
        }
private Nachricht | Beiträge des Benutzers
Rioma
myCSharp.de - Member



Dabei seit:
Beiträge: 228

Themenstarter:

beantworten | zitieren | melden

Das ich das nicht verhindern kann, ist mir bewusst.

Deswegen habe ich versucht, das Problem mit dem Hashset zu umgehen. Allerdings ohne erfolg. Ich bekomme 2 Mal ein true zurück und am Ende ist der Pfad nur einmal drin.

Füge ich die Datei nun ein weiteres Mal hinzu, gibt es keine Probleme. Die events sind einfach zu kurz hintereinander.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.852

beantworten | zitieren | melden

Race Condition, da Du in verschiedenen Thread bist und vergessen hast zu synchronisieren?
private Nachricht | Beiträge des Benutzers
Rioma
myCSharp.de - Member



Dabei seit:
Beiträge: 228

Themenstarter:

beantworten | zitieren | melden

Ich hatte anfangs nicht daran gedacht, allerdings dann hinzugefügt.

Funktionieren tut es aber nur, wenn das Hashset static ist. Woran liegt das?
Ohne static befindet sich die variable auf Instanz-Ebene und davon sollte es nur eine geben.

Erzeugt wird diese von Topshelf:


   HostFactory.Run(config =>
            {
                // Pass it to Topshelf
                config.UseSimpleInjector(_container);
                config.UseNLog();

                config.Service<Service>(s => //Service ist die Instanz
                {
                    s.ConstructUsingSimpleInjector();
                    s.WhenStarted((service, control) => service.Start(control));
                    s.WhenStopped((service, control) => service.Stop(control));
                });

                config.RunAsLocalSystem();                            

            });
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Rioma am .
private Nachricht | Beiträge des Benutzers