FileSystemWatcher vs interrogation pour surveiller les modifications de fichiers

152

J'ai besoin de configurer une application qui surveille les fichiers créés dans un répertoire, à la fois localement ou sur un lecteur réseau.

Le FileSystemWatcherou l'interrogation sur une minuterie serait la meilleure option. J'ai utilisé les deux méthodes dans le passé, mais pas de manière extensive.

Quels sont les problèmes (performances, fiabilité, etc.) avec l'une ou l'autre méthode?

Jon Tackabury
la source
3
FileSystemWatcher est une abstraction qui fuit et ne peut être invoqué que pour les cas les plus élémentaires. Voir ici: stackoverflow.com/a/22768610/129130
Stein Åsmul
1
Vous souhaitez ajouter un lien de référence à cette réponse de Raymond Chen (expert Microsoft) sur le sujet de la fiabilité de FileSystemWatcher . Et son blog: The Old New Thing (recherchez FileSystemWatcher par exemple).
Stein Åsmul

Réponses:

105

J'ai vu l'échec de l'observateur du système de fichiers dans les environnements de production et de test. Je considère maintenant que c'est pratique, mais je ne le considère pas comme fiable. Mon modèle a été de surveiller les changements avec l'observateur du système de fichiers, mais d'interroger occasionnellement pour détecter les changements de fichiers manquants.

Modifier: si vous disposez d'une interface utilisateur, vous pouvez également donner à votre utilisateur la possibilité de "rafraîchir" les modifications au lieu d'interroger. Je combinerais cela avec un observateur de système de fichiers.

Jason Jackson
la source
11
J'ai vu si tomber aussi. La solution que nous avons utilisée est d'envelopper notre propre classe, où la classe wrapper utilise ÉGALEMENT une minuterie pour vérifier à l'occasion que l'observateur fonctionne toujours.
Joel Coehoorn
Nous faisons quelque chose de similaire - une fois que nous avons traité le fichier passé dans l'événement FileCreated, nous vérifions manuellement tous les autres nouveaux fichiers avant de revenir. Cela semble atténuer les problèmes survenant avec l'arrivée de nombreux fichiers en même temps.
John Sibly
4
Je crois que nous l'avons testé sous XP et Server 2003 sur un répertoire local et un partage de fichiers, et avions des machines XP sur le terrain. Nous avons eu des problèmes avec le répertoire local et le partage de fichiers. L'une des causes probables que nous avons trouvées était la copie / création d'un grand nombre de fichiers en peu de temps dans le répertoire.
Jason Jackson
5
Ce n'est pas très constructif ni professionnel de dire simplement "j'ai vu un fantôme un jour". Il semble que les gens en bas du fil, mentionnant le document msdn sur les dépassements de tampon non-page-outable pourraient expliquer vos problèmes. Avez-vous essayé d'utiliser l'approche de Brent?
v.oddou
4
Je viens d'acheter un capteur de gaz sur Amazon et je suis étonné de voir combien de personnes ont dit que cela ne fonctionnait pas, alors qu'ils ne l'avaient manifestement pas calibré correctement ou ne connaissaient même pas l'étalonnage ... FileSystemWatcher a des limitations connues avec un trafic élevé de sa taille de tampon. Presque garanti que c'est la raison de son "échec". Ceci est facilement expliqué dans la documentation et il existe des solutions de contournement qui fournissent un fonctionnement très fiable (comme indiqué ci-dessous). Ce n'est pas une bonne réponse pour dire simplement "euh, quelque chose n'a pas fonctionné une fois, je ne sais pas pourquoi ... personne ne devrait s'y fier".
u8it le
60

Le plus gros problème que j'ai eu est des fichiers manquants lorsque la mémoire tampon est pleine. Facile à réparer - augmentez simplement le tampon. N'oubliez pas qu'il contient les noms de fichiers et les événements, augmentez-le donc au nombre de fichiers attendu (essais et erreurs). Il utilise de la mémoire qui ne peut pas être paginée, de sorte qu'il pourrait forcer d'autres processus à paginer si la mémoire devient faible.

Voici l'article MSDN sur le tampon: FileSystemWatcher .. ::. Propriété InternalBufferSize

Par MSDN:

L'augmentation de la taille de la mémoire tampon coûte cher, car elle provient de la mémoire non paginée qui ne peut pas être échangée sur le disque, alors gardez la mémoire tampon aussi petite que possible. Pour éviter un dépassement de mémoire tampon, utilisez les propriétés NotifyFilter et IncludeSubdirectories pour filtrer les notifications de modification indésirables.

Nous utilisons 16 Mo en raison d'un lot important attendu à la fois. Fonctionne bien et ne manque jamais un fichier.

Nous lisons également tous les fichiers avant de commencer à en traiter un seul ... récupérez les noms de fichiers en toute sécurité (dans notre cas, dans une table de base de données), puis traitez-les.

Pour les problèmes de verrouillage de fichier, je lance un processus qui attend que le fichier soit déverrouillé en attendant une seconde, puis deux, puis quatre, et cetera. Nous ne sondons jamais . Celui-ci est en production sans erreur depuis environ deux ans.


la source
12
Débordement de tampon? Oh, vous voulez dire un débordement de pile.
TheFlash
1
À partir de .NET 3.5: "Vous pouvez définir la mémoire tampon sur 4 Ko ou plus, mais elle ne doit pas dépasser 64 Ko"
brad
9
Comment utilisez-vous 16 Mo si la mémoire tampon interne maximale pour FileSystemWatcher est de 64 Ko?
BK
1
@ Jarvis, un tampon est un emplacement de stockage tempéré configuré pour contenir les informations telles qu'elles sont transmises jusqu'à ce qu'elles puissent être traitées, cela signifie généralement une FIFO ou une file d'attente car vous souhaitez traiter les demandes dans l'ordre où elles arrivent cependant dans certains processus comme la récursivité dans les programmes une structure FILO ou Stack est ce qui est utilisé, Dans ce cas, nous nous référons définitivement au tampon de la file d'attente d'événements et non au tampon de la pile des appels des programmes
MikeT
35

Le FileSystemWatcherpeut également manquer des modifications pendant les périodes de pointe, si le nombre de modifications en file d'attente dépasse la mémoire tampon fournie. Il ne s'agit pas d'une limitation de la classe .NET en soi, mais de l'infrastructure Win32 sous-jacente. D'après notre expérience, le meilleur moyen de minimiser ce problème est de retirer les notifications de la file d'attente le plus rapidement possible et de les traiter sur un autre fil.

Comme mentionné par @ChillTemp ci-dessus, l'observateur peut ne pas fonctionner sur les partages non Windows. Par exemple, cela ne fonctionnera pas du tout sur les lecteurs Novell montés.

Je conviens qu'un bon compromis est de faire un sondage occasionnel pour relever les changements manqués.

Brent Rockwood
la source
4
L'observateur du système de fichiers peut commencer à générer de nombreux événements en succession rapide. Si vous ne pouvez pas exécuter votre gestionnaire d'événements au moins aussi rapidement qu'ils sont déclenchés, le gestionnaire commencera finalement à déposer des événements sur le sol et vous manquerez des choses.
Brent Rockwood
17

Notez également que l'observateur du système de fichiers n'est pas fiable sur les partages de fichiers. Surtout si le partage de fichiers est hébergé sur un serveur non Windows. FSW ne doit pas être utilisé pour quelque chose de critique. Ou devrait être utilisé avec un sondage occasionnel pour vérifier qu'il n'a rien manqué.

chilltemp
la source
3
Microsoft a-t-il reconnu qu'il n'était pas fiable sur les partages de fichiers non Windows? Nous vivons certainement cette première main depuis le passage d'un partage Windows à un partage SMB basé sur Linux.
Sean
1
Pas que je sache. Et je suis sûr que ce serait simplement un jeu de blâme entre les différents fournisseurs.
chilltemp
1
Nous avons rencontré des problèmes avec l'observateur du système de fichiers sur les lecteurs mappés. Si la carte se déconnecte, puis se reconnecte, l'observateur de fichiers ne déclenche plus de modifications. Facilement résolu mais toujours une grève contre l'observateur de système de fichiers IMHO.
Richard Dorman
11

Personnellement, j'ai utilisé le FileSystemWatchersur un système de production, et cela a bien fonctionné. Au cours des 6 derniers mois, il n'y a pas eu un seul hoquet fonctionnant 24x7. Il surveille un seul dossier local (qui est partagé). Nous avons un nombre relativement restreint d'opérations sur les fichiers à gérer (10 événements déclenchés par jour). Ce n'est pas quelque chose dont j'ai jamais eu à m'inquiéter. Je l'utiliserais à nouveau si je devais refaire la décision.

Jim
la source
7

J'utilise actuellement le FileSystemWatcher sur un fichier XML mis à jour en moyenne toutes les 100 millisecondes.

J'ai trouvé que tant que le FileSystemWatcherest correctement configuré, vous ne devriez jamais avoir de problèmes avec le local fichiers .

Je n'ai aucune expérience de l'observation de fichiers à distance et des partages non Windows.

Je considérerais que l'interrogation du fichier est redondante et ne vaut pas la peine, à moins que vous ne vous méfiiez intrinsèquement du FileSystemWatcherou que vous ayez directement expérimenté les limitations que tout le monde a répertoriées ici (partages non Windows et observation de fichiers à distance).

PersistenceOfVision
la source
5

J'irais avec le sondage.

Les problèmes de réseau font que le FileSystemWatchern'est pas fiable (même lors de la surcharge de l'événement d'erreur).

bleuâtre
la source
5

J'ai rencontré des problèmes lors de l'utilisation FileSystemWatcherdes partages réseau. Si vous êtes dans un environnement Windows pur, ce n'est peut-être pas un problème, mais je regardais un partage NFS et comme NFS est sans état, il n'y a jamais eu de notification lorsque le fichier que je regardais a changé.

Jon Norton
la source
J'ai rencontré le même problème, mais c'était inattendu pour moi car FileSystemWatcher était sur le même serveur Windows qui partage le dossier en utilisant NFS. le fait de partager un dossier avec NFS fait que le filesystemwatcher ne voit pas les fichiers créés à l'aide du partage à distance (c'est-à-dire à partir d'un Linux qui mappe le partage) tandis que si j'écris un fichier sur le même dossier sous surveillance, le filesystemwatcher est déclenché. il semble que le serveur NFS écrit des fichiers en utilisant une couche inférieure et la couche api qui se déclenche si l'observateur du système de fichiers n'est pas engagé, quelqu'un a plus d'informations?
Mosè Bottacini
3

J'ai eu de gros problèmes avec FSW sur les lecteurs réseau: la suppression d'un fichier renvoyait toujours l'événement d'erreur, jamais l'événement supprimé. Je n'ai pas trouvé de solution, alors j'évite maintenant le FSW et j'utilise le sondage.

Les événements de création, en revanche, fonctionnaient bien, donc si vous n'avez besoin que de surveiller la création de fichiers, vous pouvez opter pour le FSW.

De plus, je n'ai eu aucun problème sur les dossiers locaux, qu'ils soient partagés ou non.

Treb
la source
3

Le retour de la méthode événementielle le plus rapidement possible, en utilisant un autre thread, a résolu le problème pour moi:

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    Task.Run(() => MySubmit(e.FullPath));
}
éclaboussure
la source
2

Utiliser à la fois FSW et le sondage est une perte de temps et de ressources, à mon avis, et je suis surpris que des développeurs expérimentés le suggèrent. Si vous devez utiliser l'interrogation pour vérifier d'éventuels "échecs FSW", vous pouvez, naturellement, supprimer complètement FSW et n'utiliser que l'interrogation.

J'essaie actuellement de décider si j'utiliserai FSW ou si je ferai des sondages pour un projet que je développe. En lisant les réponses, il est évident qu'il y a des cas où FSW couvre parfaitement les besoins, alors que d'autres fois, vous avez besoin d'un sondage. Malheureusement, aucune réponse n'a réellement traité de la différence de performance (le cas échéant), uniquement des problèmes de «fiabilité». Quelqu'un peut-il répondre à cette partie de la question?

MODIFIER: nmclean le point de pour la validité de l'utilisation à la fois de FSW et d'interrogation (vous pouvez lire la discussion dans les commentaires, si vous êtes intéressé) semble être une explication très rationnelle pourquoi il peut y avoir des situations où l'utilisation à la fois d'un FSW et de l'interrogation est efficace. Merci d'avoir fait la lumière là-dessus pour moi (et pour toute autre personne ayant le même avis), nmclean .

ThunderGr
la source
1
Que faire si vous souhaitez répondre le plus rapidement possible aux modifications de fichiers? Si vous interrogez une fois par minute, par exemple, vous pourriez avoir jusqu'à 1 minute de retard entre un changement de fichier et votre application prend en charge le changement. L'événement FSW serait vraisemblablement déclenché bien avant cela. Ainsi, en utilisant les deux, vous gérez les événements avec le moins de retard possible, mais vous récupérez également les événements manqués s'il y en a.
rom99
@ rom99 Exactement mon point. Si le FSW n'est pas fiable dans les cas où vous avez besoin d'une réponse rapide, il ne sert à rien de l'utiliser, car vous aurez des cas où il n'y aura pas de réponse rapide, ainsi, votre application ne sera pas fiable. Interroger à des intervalles plus courts, dans un fil, serait ce que vous devez faire. En faisant les deux , cela signifie que vous avez une tolérance dans les temps de réponse que couvre le sondage, alors pourquoi ne pas utiliser uniquement le sondage?
ThunderGr
5
@ThunderGr "ainsi, votre application ne sera pas fiable." - Dans de nombreux cas, la vitesse n'est pas une condition préalable à la fiabilité. Le travail doit être fait, mais cela peut attendre un certain temps. Si nous combinons une interrogation lente et fiable avec un FSW rapide et peu fiable , nous obtenons une application toujours fiable et parfois rapide, ce qui est mieux que fiable et jamais rapide. Nous pouvons supprimer FSW et obtenir le même temps de réponse maximal en effectuant une interrogation constante, mais cela se fait au détriment de la réactivité du reste de l'application, donc ne devrait être fait que si une réponse immédiate est absolument nécessaire.
nmclean
2
Maintenant, pourquoi ce qui précède est-il un mauvais argument? Parce que, bien que nous ayons toujours besoin d'un accès disque, nous en avons moins besoin . De même, vous pouvez interroger moins. Ce n'est pas parce que nous vérifions toujours tous les fichiers que la charge de travail est la même. Votre déclaration, «l'interrogation coûte cher en temps CPU avec FSW ou non», est fausse . En déchargeant le souci «d'immédiateté» à FSW, nous pouvons changer l'interrogation en une tâche inactive et de faible priorité, de sorte que l'occupation de l'application à un moment donné soit considérablement réduite tout en offrant le «plaisir» de l'immédiateté. Vous ne pouvez tout simplement pas atteindre le même équilibre avec le seul sondage.
nmclean
9
@nmclean Merci d'avoir pris le temps et l'énergie de clarifier cela comme vous l'avez fait. Quand vous le dites ainsi, cela a sûrement beaucoup plus de sens. Tout comme il y a des moments où un cache ne convient pas à votre problème spécifique, le FSW (quand il s'avère peu fiable) peut ne pas convenir. Il s'avère que vous aviez raison depuis le début. Je suis désolé qu'il m'ait fallu tant de temps pour l'obtenir.
ThunderGr
1

Solution de travail pour travailler avec créer un événement au lieu de modifier

Même pour copier, couper, coller, déplacer.

class Program
{        

        static void Main(string[] args)
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";
            FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
            FileSystemWatcher.Path = SourceFolderPath;
            FileSystemWatcher.IncludeSubdirectories = false;
            FileSystemWatcher.NotifyFilter = NotifyFilters.FileName;   // ON FILE NAME FILTER       
            FileSystemWatcher.Filter = "*.txt";         
             FileSystemWatcher.Created +=FileSystemWatcher_Created; // TRIGGERED ONLY FOR FILE GOT CREATED  BY COPY, CUT PASTE, MOVE  
            FileSystemWatcher.EnableRaisingEvents = true;

            Console.Read();
        }     

        static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {           
                string SourceFolderPath = "D:\\SourcePath";
                string DestinationFolderPath = "D:\\DestinationPath";

                try
                {
                    // DO SOMETING LIKE MOVE, COPY, ETC
                    File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
                }
                catch
                {
                }          
        }
}

Solution pour cet observateur de fichiers lors de l'événement de changement d'attribut de fichier à l'aide du stockage statique

class Program
{
    static string IsSameFile = string.Empty;  // USE STATIC FOR TRACKING

    static void Main(string[] args)
    {
         string SourceFolderPath = "D:\\SourcePath";
        string DestinationFolderPath = "D:\\DestinationPath";
        FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
        FileSystemWatcher.Path = SourceFolderPath;
        FileSystemWatcher.IncludeSubdirectories = false;
        FileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;          
        FileSystemWatcher.Filter = "*.txt";         
        FileSystemWatcher.Changed += FileSystemWatcher_Changed;
        FileSystemWatcher.EnableRaisingEvents = true;

        Console.Read();
    }     

    static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        if (e.Name == IsSameFile)  //SKIPS ON MULTIPLE TRIGGERS
        {
            return;
        }
        else
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";

            try
            {
                // DO SOMETING LIKE MOVE, COPY, ETC
                File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
            }
            catch
            {
            }
        }
        IsSameFile = e.Name;
    }
}

Il s'agit d'une solution de contournement pour ce problème d'événement déclencheur multiple.

Mark Macneil Bikeio
la source
0

Je dirais utiliser l'interrogation, en particulier dans un scénario TDD, car il est beaucoup plus facile de simuler / stub la présence de fichiers ou autrement lorsque l'événement d'interrogation est déclenché que de s'appuyer sur l'événement fsw plus «incontrôlé». + à cela après avoir travaillé sur un certain nombre d'applications qui étaient en proie à des erreurs fsw.

user2819502
la source