381 votes

L'événement FileSystemWatcher Changed est déclenché deux fois

J'ai une application où je suis à la recherche d'un fichier texte et si des modifications sont apportées au fichier, j'utilise le gestionnaire d'événement OnChanged pour gérer l'événement. J'utilise le NotifyFilters.LastWriteTime mais l'événement se déclenche deux fois. Voici le code.

 public void Initialize()
{
   FileSystemWatcher _fileWatcher = new FileSystemWatcher();
  _fileWatcher.Path = "C:\\Folder";
  _fileWatcher.NotifyFilter = NotifyFilters.LastWrite;
  _fileWatcher.Filter = "Version.txt";
  _fileWatcher.Changed += new FileSystemEventHandler(OnChanged);
  _fileWatcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
   .......
}
 

Dans mon cas, le OnChanged est appelé deux fois, quand je change le fichier texte version.txt et le sauvegarde.

298voto

Jørn Schou-Rode Points 19947

Je crains que ce est un fait bien connu bug/feature de l' FileSystemWatcher classe. C'est à partir de la documentation de la classe:

Vous remarquerez peut-être dans certaines situations que d'un seul événement de création génère de multiples Créé des événements qui sont gérés par votre composant. Par exemple, si vous utilisez un FileSystemWatcher composante de suivi de la création de nouveaux fichiers dans un répertoire, puis de le tester en utilisant le bloc-notes pour créer un fichier, vous pouvez voir les deux, ils ont Créé les événements générés, même si un seul fichier a été créé. C'est parce que le bloc-notes effectue de fichiers multiples actions du système pendant le processus d'écriture. Le bloc-notes écrit sur le disque dans les lots de créer le contenu du fichier et ensuite les attributs de fichier. Autres applications peuvent fonctionner de la même manière. Parce que FileSystemWatcher surveille le système d'exploitation activités, tous les événements que ces applications d'incendie doit être ramassé.

Maintenant ce morceau de texte est sur l' Created événement, mais la même chose s'applique à d'autres événements de fichier. Dans certaines applications, vous pourriez être en mesure de contourner ce problème en utilisant l' NotifyFilter de la propriété, mais mon expérience est dit que, parfois, vous devez faire quelques manuelle double filtrage (hacks).

Il y a un moment que je bookedmarked une page avec quelques FileSystemWatcher conseils. Vous pourriez vouloir vérifier.

159voto

David Brabant Points 11159

J'ai "résolu" ce problème en utilisant la stratégie suivante dans mon délégué:

 // fsw_ is the FileSystemWatcher instance used by my application.

private void OnDirectoryChanged(...)
{
   try
   {
      fsw_.EnableRaisingEvents = false;

      /* do my stuff once */
   }

   finally
   {
      fsw_.EnableRaisingEvents = true;
   }
}
 

115voto

BaBu Points 807

Tous dupliquée OnChanged des événements de la FileSystemWatcher peuvent être détectés et mis au rebut en cochant la File.GetLastWriteTime horodatage sur le fichier en question. Ainsi:

 DateTime lastRead = DateTime.MinValue;

void OnChanged(object source, FileSystemEventArgs a)
{
    DateTime lastWriteTime = File.GetLastWriteTime(uri);
    if (lastWriteTime != lastRead)
    {
        doStuff();
        lastRead = lastWriteTime;
    }
    // else discard the (duplicated) OnChanged event
}
 

25voto

Deepashri Points 101

Voici ma solution qui m'a aidé à arrêter deux fois l'évènement:

 watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
 

Ici, j'ai défini la propriété NotifyFilter avec uniquement le nom de fichier et la taille.
watcher est mon objet de FileSystemWatcher. J'espère que cela aidera.

9voto

Ikon Points 377

Mon scénario est que j'ai une machine virtuelle avec un serveur Linux. Je suis en train d'élaborer des fichiers sur l'hôte Windows. Quand je change quelque chose dans un dossier sur l'ordinateur hôte, je veux que toutes les modifications apportées à être téléchargé, synchronisés sur le serveur virtuel via Ftp. C'est comment je le fais éliminer le double événement de changement quand j'écris dans un fichier ( qui signale le dossier contenant le fichier à modifier ) :

private Hashtable fileWriteTime = new Hashtable();

private void fsw_sync_Changed(object source, FileSystemEventArgs e)
{
    string path = e.FullPath.ToString();
    string currentLastWriteTime = File.GetLastWriteTime( e.FullPath ).ToString();

    // if there is no path info stored yet
    // or stored path has different time of write then the one now is inspected
    if ( !fileWriteTime.ContainsKey(path) ||
         fileWriteTime[path].ToString() != currentLastWriteTime
    )
    {
        //then we do the main thing
        log( "A CHANGE has occured with " + path );

        //lastly we update the last write time in the hashtable
        fileWriteTime[path] = currentLastWriteTime;
    }
}

Surtout, je créer une table de hachage pour stocker des fichiers écrire des informations en temps. Ensuite, si la table de hachage est le chemin d'accès du fichier qui est modifié et il est temps de la valeur est la même que la notifiées actuellement du fichier changer alors je sais que c'est le double de l'événement et de l'ignorer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X