2009-10-15 9 views
6

FileSystemWatcher non funziona correttamente quando molti file vengono aggiunti alla directory allo stesso tempo ...FileSystemWatcher non funziona correttamente quando molti file vengono aggiunti alla directory allo stesso tempo

The Watcher non si limita a trova tutti i file nella directory - solo se i file vengono inseriti nella cartella uno per uno - non se molti file vengono copiati contemporaneamente nella cartella ...

È la creazione di Thread la soluzione a il problema o c'è un altro modo per gestire il problema?

+1

Ricordare che FileSystemWatcher si basa sul sistema operativo per segnalare quando i file vengono aggiunti/modificati/eliminati/ecc. Quindi avere più istanze non aiuterà. –

risposta

11

Le documentation on that class dettagli che problema:

Il sistema operativo Windows segnala il componente di modifiche apportate ai file in un buffer creato dal FileSystemWatcher. Se ci sono molti cambiamenti in poco tempo, il buffer può traboccare. Ciò fa sì che il componente perda traccia delle modifiche nella directory e fornirà solo una notifica generale. Aumentare la dimensione del buffer con la proprietà InternalBufferSize è costoso, poiché proviene da una memoria non di paging che non può essere scambiata su disco, quindi mantenere il buffer piccolo ma sufficientemente grande da non perdere eventi di modifica dei file. Per evitare un overflow del buffer, utilizzare le proprietà NotifyFilter e IncludeSubdirectories in modo da poter filtrare le notifiche di modifica indesiderate.

Quindi, i thread probabilmente non ti aiuteranno molto in questo caso. Probabilmente vuoi aumentare la dimensione del buffer (ma quanto dovrebbe essere grande potrebbe dipendere dalla velocità del computer e del disco stesso) o limitare i file a cui sei interessato impostando il filtro appropriato.

+1

E, naturalmente, un'altra opzione è quella di interrogare ulteriormente la cartella per i nuovi file e file che sono stati persi. –

+0

A volte sottovaluto C#, .Net ecc. Poiché lo sviluppo nel mondo Microsoft è facile (dicendo "Microsoft dovrebbe averlo pensato anche per me ...") e comportarsi in modo sdolcinato, quindi non leggere la documentazione e quindi inserire ore in piccole cose come questo lol – sotn

0

provare qualcosa di simile.

1

C# è nuovo per me e ho faticato con lo stesso problema per quasi una settimana. Ho avuto questa:

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; 
     } 
    } 

Ho anche impostare l'intervallo del timer a 1 millisecondo e tuttavia alcuni nuovi eventi di file mancavano. Ho provato ad aggiornare notificationsListBox dall'interno dell'evento onCreated ma ho sempre ricevuto un errore di riferimento incrociato. Questo è stato fino a quando ho scoperto che l'evento onCreated watcher è eseguito in un thread diverso da quello del thread del metodo principale, quindi, in una shell dado, questa è la mia soluzione:

Ho incluso public delegate void Action() come un attributo del mio classe e quindi utilizzato Invoke per aggiornare notificationsListBox dall'interno dell'evento onCreated. Successivamente, il codice pezzo:

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());})); 
    } 

Quindi il timer e il relativo codice non sono più necessari. Questo funziona eccellente per me e spero lo faccia per chiunque abbia una situazione simile. Cordiali saluti !!!

Problemi correlati