2012-10-17 25 views
8

dlaczego FileSystemWatcher strzela dwukrotnie? Czy istnieje prosty sposób, aby to naprawić? Z pewnością jeśli zaktualizuję lub edytuję plik tekstowy, powinien on być uruchamiany tylko raz?Dlaczego FileSystemWatcher strzela dwukrotnie

ten link tutaj http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx mówi

  1. Wydarzenia podnoszone dwukrotnie - Zdarzenie zostanie podniesiona dwukrotnie, jeśli obsługa zdarzeń (AddHander FSW.Created, AddressOf FSW_Created) jest wyraźnie określone. Wynika to z tego, że domyślnie publiczne zdarzenia automatycznie wywołują odpowiednie chronione metody (OnChanged, OnCreated, OnDeleted, OnRenamed). Aby rozwiązać ten problem, po prostu usuń jawny moduł obsługi zdarzeń (AddHandler ...).

Co oznacza "usunięcie jawnego programu obsługi zdarzeń"?

Imports System.IO 

Public Class Form2 

    Private Sub FileSystemWatcher1_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed 

     'this fires twice 
     MessageBox.Show("test") 

    End Sub 

    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

     FileSystemWatcher1.Path = "C:\Users\c\Desktop\test\" 
     FileSystemWatcher1.NotifyFilter = NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName Or NotifyFilters.CreationTime 

     FileSystemWatcher1.IncludeSubdirectories = False 
     FileSystemWatcher1.Filter = "text.txt" 

    End Sub 

End Class 
+0

Kiedy dokładnie doświadczasz tego * nieoczekiwanego * zachowania? Czy edytujesz plik, przenosisz, usuwasz lub tworzysz plik? – Arrow

+1

Witaj, edytuj plik, kiedy to się stanie - dziękuję –

+0

Mam zaktualizowane moje pytanie z możliwym rozwiązaniem, co najmniej coś do sprawdzenia, ponieważ może pomóc zawęzić problem. – Arrow

Odpowiedz

8

Aktualizacja:

I mają pochodzić z 2 rozwiązań. Jeden używa wątków, a drugi nie. Wybierz :-).

bez przewlekania

Imports System.IO 

Public Class Form1 
    Private Sub FileSystemWatcher1_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed 
     Dim watcher As System.IO.FileSystemWatcher = sender 
     watcher.EnableRaisingEvents = False 

     'Do work here while new events are not being raised. 
     MessageBox.Show("Test") 

     watcher.EnableRaisingEvents = True 'Now we can begin watching for new events. 

    End Sub 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

     FileSystemWatcher1.Path = "C:\Users\c\Desktop\test" 
     FileSystemWatcher1.NotifyFilter = NotifyFilters.LastWrite 
     FileSystemWatcher1.IncludeSubdirectories = False 
     FileSystemWatcher1.Filter = "test.txt" 


    End Sub 

    Private Sub FileSystemWatcher_OnChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) 

    End Sub 

End Class 

Roztwór ten (bez gwintowania) ustawia watcher.EnableRaisingEvents False. To właśnie w tym miejscu normalnie przetwarzasz pliki, na które mają wpływ (lub zostały zmienione). Następnie ustawia EnableRaisingEvents na True po zakończeniu pracy.

z przewlekania

Imports System.IO 

Public Class Form1 
    Private Sub FileSystemWatcher1_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed 
     FileSystemWatcher1.EnableRaisingEvents = False 
     Threading.Thread.Sleep(250) 
     FileSystemWatcher1.EnableRaisingEvents = True 


     MessageBox.Show("test") 


    End Sub 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

     FileSystemWatcher1.Path = "C:\Users\c\Desktop\test" 
     FileSystemWatcher1.NotifyFilter = NotifyFilters.LastWrite 
     FileSystemWatcher1.IncludeSubdirectories = False 
     FileSystemWatcher1.Filter = "test.txt" 


    End Sub 

    Private Sub FileSystemWatcher_OnChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) 

    End Sub 

End Class 

Rozwiązanie to, choć nieco hacky, działa. Wyłącza sprawdzanie nowych zmian/zdarzeń przez 250ms, a następnie ponownie włącza sprawdzanie, opierając się na założeniu, że nie będziesz musiał sprawdzać zmiany co 250ms. Wypróbowałem prawie wszystko, co mogłem wymyślić, aby uzyskać dla ciebie prawdziwe rozwiązanie, ale to zadziała w międzyczasie.

+1

Widziałem tego typu rozwiązanie stosowane wcześniej również w innych postach w Internecie. To też zadziałało dobrze dla mnie.Microsoft Objaśnia to na http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx – JimDel

+0

Dziękuję. Właśnie znalazłem bardziej odpowiednie, praktyczne rozwiązanie, które jest bardzo podobne, chociaż nie wymaga użycia nici. Aktualizuję teraz. – Arrow

+0

Dzięki, pierwsza technika zadziałała dla mnie. Używałem 'FileSystemWatcher' w małej usłudze Windows, która kompilowała arkusze stylów do użycia przez LiveReload, a zdarzenia związane z wieloma zmianami grzęzły w przeglądarce. Jednak ta niewielka korekta rozwiązała problem związany z [FUOC] (http://www.bluerobot.com/web/css/fouc.asp/). ;) – harpo

1

Sprawdź e.ChangeType. Wyobrażam sobie, że otrzymujesz dwa różne powiadomienia. Być może LastAccess i LastModified. W takim przypadku jest to oczekiwane zachowanie.

+0

dzięki ale jeśli wziąć te się to jeszcze dwa razy pożary –