2009-10-15 18 views
6

FileSystemWatcher nie działa poprawnie, gdy wiele plików są dodawane do katalogu, w tym samym czasie ...FileSystemWatcher nie działa poprawnie, gdy wiele plików są dodawane do katalogu, w tym samym czasie

Obserwator po prostu nie robi znajdź wszystkie pliki w katalogu - tylko jeśli pliki są umieszczane w folderze jeden po drugim - nie, jeśli wiele plików jest kopiowanych do folderu w tym samym czasie ...

Czy tworzenie wątków jest rozwiązaniem problem lub czy istnieje inny sposób radzenia sobie z problemem?

+1

Należy pamiętać, że FileSystemWatcher polega na systemie operacyjnym, który sygnalizuje, kiedy pliki są dodawane/modyfikowane/usuwane/itd. Zatem posiadanie wielu instancji nie pomoże. –

Odpowiedz

11

W documentation on that class szczegóły, które Problem:

System operacyjny Windows powiadamia swój składnik zmian plików w buforze stworzonej przez FileSystemWatcher. Jeśli istnieje wiele zmian w krótkim czasie, bufor może zostać przepełniony. Powoduje to, że komponent traci ślad zmian w katalogu i zapewnia tylko ogólne powiadomienie. Zwiększenie rozmiaru bufora przy użyciu właściwości InternalBufferSize jest kosztowne, ponieważ pochodzi z niestronicowanej pamięci, której nie można zamienić na dysk, dlatego należy utrzymywać bufor jako mały, ale wystarczająco duży, aby nie pominąć żadnych zdarzeń zmiany pliku. Aby uniknąć przepełnienia bufora, użyj właściwości NotifyFilter i IncludeSubdirectories, aby odfiltrować niechciane powiadomienia o zmianach.

Nici prawdopodobnie nie pomogą w tym przypadku. Prawdopodobnie chcesz zwiększyć rozmiar bufora (ale jak duża powinna być zależna od prędkości komputera i samego dysku) lub ograniczyć pliki, które Cię interesują, ustawiając odpowiedni filtr.

+1

I, oczywiście, inną opcją jest dodatkowo odpytywanie folderu o nowe pliki i pliki, które zostały pominięte. –

+0

Czasami nie doceniam C#, .Net itd., Ponieważ rozwój w świecie Microsoftu jest łatwy (mówiąc: "Microsoft powinien pomyśleć, że dla mnie też ...") i zachowują się pewnie, więc nie czytaj dokumentacji, a potem godzinami zajmuj się drobiazgami jak ten jeden lol – sotn

0

spróbuj czegoś takiego.

public MainWindow() 
    { 
     InitializeComponent(); 

     #region initialise FileSystemWatcher 
     FileSystemWatcher watch = new FileSystemWatcher(); 
     watch.Path = folder; 
     watch.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName; 
     watch.Filter = ext; 
     watch.Changed += new FileSystemEventHandler(OnChanged); 
     watch.Created += new FileSystemEventHandler(OnChanged); 
     watch.EnableRaisingEvents = true; 
     #endregion 

    } 

private void OnChanged(object source, FileSystemEventArgs e) 
    { 
     Application.Current.Dispatcher.BeginInvoke((Action)delegate 
     { 
      // do your work here. If this work needs more time than it can be processed, not the filesystembuffer overflows but your application will block. In this case try to improve performance here. 
     }, System.Windows.Threading.DispatcherPriority.Normal); 
    } 
1

C# jest dla mnie nowy i zmagałem się z tymi samymi problemami przez prawie tydzień. Miałem to:

private void btnWatchFile_Click(object sender, EventArgs e) 
    { 
     //code to create a watcher and allow it to reise events... 
    } 

    //watcher onCreate event 
    public void onCreated(object sender, FileSystemEventArgs e) 
    { 
     if (!updateNotifications) 
     { 
      stringBuilder.Remove(0, stringBuilder.Length); 
      stringBuilder.Append(e.FullPath); 
      stringBuilder.Append(" "); 
      stringBuilder.Append(e.ChangeType.ToString()); 
      stringBuilder.Append(" "); 
      stringBuilder.Append(DateTime.Now.ToString()); 
      updateNotifications = true; 
     } 
    } 

    //timer to check the flag every X time 
    private void timer_Tick(object sender, EventArgs e) 
    { 
     if (updateNotifications) 
     { 
      notificationListBox.Items.Insert(0, stringBuilder.ToString()); 
      updateNotifications = false; 
     } 
    } 

I nawet ustawić interwał czasowy do do 1 milisekundy i jeszcze kilka nowych wydarzeń plików brakowało. Próbowałem zaktualizować notificationsListBox od wewnątrz zdarzenia onCreated, ale zawsze otrzymałem komunikat Odsyłacz. To było, dopóki nie odkryłem, że zdarzenie obserwatora jest wykonywane w wątku innym niż główny wątek metody, więc w powłoce nakrętki jest to moje rozwiązanie:

Dołączyłem public delegate void Action() jako atrybut mojego klasy, a następnie użył Invoke, aby zaktualizować notificationsListBox ze zdarzenia onCreated. Następnie kod utworu:

public void onCreated(object sender, FileSystemEventArgs e) 
    { 
     stringBuilder.Remove(0, stringBuilder.Length); 
     stringBuilder.Append(e.FullPath); 
     stringBuilder.Append(" "); 
     stringBuilder.Append(e.ChangeType.ToString()); 
     stringBuilder.Append(" "); 
     stringBuilder.Append(DateTime.Now.ToString()); 
     updateNotifications = true; 
     Invoke((Action)(() => {notificationListBox.Items.Insert(0, stringBuilder.ToString());})); 
    } 

Tak więc timer i jego kod nie są już potrzebne. To działa doskonale dla mnie i mam nadzieję, że zrobi to dla każdego, kto ma podobną sytuację. Pozdrawiam !!!

Powiązane problemy