FileSystemWatcher vs sondeo para ver los cambios de archivo

152

Necesito configurar una aplicación que vigile los archivos que se crean en un directorio, tanto localmente como en una unidad de red.

¿ FileSystemWatcherSería la mejor opción el sondeo en un temporizador? He usado ambos métodos en el pasado, pero no ampliamente.

¿Qué problemas (rendimiento, confiabilidad, etc.) existen con cualquiera de los métodos?

Jon Tackabury
fuente
3
FileSystemWatcher es una abstracción permeable y no se puede confiar en nada más que en los casos más básicos. Ver aquí: stackoverflow.com/a/22768610/129130
Stein Åsmul
1
Desea agregar un enlace para referencia a esta respuesta de Raymond Chen (experto de Microsoft) sobre el tema de la confiabilidad de FileSystemWatcher . Y su blog: The Old New Thing (busque FileSystemWatcher por ejemplo).
Stein Åsmul

Respuestas:

105

He visto fallar al observador del sistema de archivos en entornos de producción y prueba. Ahora lo considero una conveniencia, pero no lo considero confiable. Mi patrón ha sido observar los cambios con el observador del sistema de archivos, pero sondear ocasionalmente para detectar los cambios que faltan.

Editar: si tiene una interfaz de usuario, también puede darle a su usuario la posibilidad de "actualizar" los cambios en lugar de sondear. Combinaría esto con un observador del sistema de archivos.

Jason Jackson
fuente
11
También he visto si se caen. La solución que hemos usado es envolver nuestra propia clase, donde la clase de envoltura TAMBIÉN usa un temporizador para verificar en ocasiones que el observador todavía esté funcionando.
Joel Coehoorn
Hacemos algo similar: una vez que procesamos el archivo pasado al evento FileCreated, hacemos una comprobación manual de cualquier otro archivo nuevo antes de regresar. Esto parece mitigar cualquier problema que ocurra con la llegada de muchos archivos a la vez.
John Sibly
44
Creo que lo probamos en XP y Server 2003 en un directorio local y un recurso compartido de archivos, y teníamos máquinas XP en el campo. Tuvimos problemas con el directorio local y el uso compartido de archivos. Una de las causas probables que se nos ocurrió fue la copia / creación de muchos archivos en un corto período de tiempo en el directorio.
Jason Jackson
55
No es muy constructivo ni profesional decir simplemente "he visto un fantasma algún día". Parece que las personas en el hilo, mencionando el documento msdn sobre desbordamientos de búfer que no se pueden borrar de la página, podrían explicar sus problemas. ¿Has intentado usar el enfoque de Brent?
v.oddou
44
Acabo de comprar un sensor de gas en Amazon y me sorprendió la cantidad de personas que dijeron que no funcionaba, cuando obviamente no lo calibraron correctamente o ni siquiera sabían acerca de la calibración ... FileSystemWatcher ha conocido limitaciones con alto tráfico de Su tamaño de búfer. Casi garantizado esa es la razón por la que "falla". Esto se explica fácilmente en la documentación y existen soluciones alternativas que proporcionan un funcionamiento muy confiable (como se publica a continuación). Esta no es una buena respuesta para decir "errr, algo no funcionó esa vez, no estoy seguro de por qué ... nadie debería confiar en eso".
u8it
60

El mayor problema que he tenido es la falta de archivos cuando el búfer se llena. Fácil de arreglar, simplemente aumente el búfer. Recuerde que contiene los nombres de archivos y eventos, así que aumente a la cantidad esperada de archivos (prueba y error). Utiliza memoria que no se puede paginar, por lo que podría forzar a otros procesos a buscar si la memoria es baja.

Aquí está el artículo de MSDN sobre el buffer: FileSystemWatcher .. ::. InternalBufferSize Property

Por MSDN:

El aumento del tamaño del búfer es costoso, ya que proviene de la memoria no paginada que no se puede cambiar al disco, por lo que debe mantener el búfer lo más pequeño posible. Para evitar un desbordamiento del búfer, use las propiedades NotifyFilter e IncludeSubdirectories para filtrar las notificaciones de cambios no deseados.

Usamos 16 MB debido a un gran lote esperado a la vez. Funciona bien y nunca pierde un archivo.

También leemos todos los archivos antes de comenzar a procesar incluso uno ... obtener los nombres de los archivos almacenados en caché de forma segura (en nuestro caso, en una tabla de base de datos) y luego procesarlos.

Para problemas de bloqueo de archivos, engendro un proceso que espera que el archivo se desbloquee esperando un segundo, luego dos, luego cuatro, etc. Nosotros no Poll. Esto ha estado en producción sin error durante aproximadamente dos años.


fuente
12
¿Desbordamiento de búfer? Ah, te refieres a desbordamiento de pila.
TheFlash el
1
A partir de .NET 3.5: "Puede establecer el búfer en 4 KB o más, pero no debe superar los 64 KB"
brad
9
¿Cómo utiliza 16 MB si el búfer interno máximo para FileSystemWatcher es de 64 KB?
BK
1
@ Jarvis, un búfer es una ubicación de almacenamiento temporal configurada para contener la información a medida que se transmite hasta que pueda procesarse, esto generalmente significa una FIFO o cola, ya que desea atender las solicitudes en el orden en que llegan, sin embargo, en algunos procesos, como la recursión en los programas Se utiliza una estructura FILO o Stack. En este caso, definitivamente nos estamos refiriendo al búfer de la cola de eventos y no al búfer de la pila de llamadas de programas
MikeT
1
petermeinl.wordpress.com/2015/05/18/tamed-filesystemwatcher Esta publicación comparte envoltorios robustos alrededor del FileSystemWatcher (FSW) estándar que soluciona los problemas comúnmente encontrados cuando se usa para monitorear el sistema de archivos en aplicaciones del mundo real.
Kiquenet
35

También FileSystemWatcherpuede perder los cambios durante las horas de mayor actividad, si el número de cambios en cola desborda el búfer proporcionado. Esto no es una limitación de la clase .NET per se, sino de la infraestructura subyacente de Win32. En nuestra experiencia, la mejor manera de minimizar este problema es retirar las notificaciones lo más rápido posible y tratarlas en otro hilo.

Como se mencionó anteriormente en @ChillTemp, el observador puede no funcionar en recursos compartidos que no sean de Windows. Por ejemplo, no funcionará en absoluto en unidades Novell montadas.

Estoy de acuerdo en que un buen compromiso es hacer una encuesta ocasional para recoger los cambios perdidos.

Brent Rockwood
fuente
44
El observador del sistema de archivos puede comenzar a generar muchos eventos en rápida sucesión. Si no puede ejecutar su controlador de eventos al menos tan rápido como se están disparando, eventualmente el controlador comenzará a soltar eventos en el piso y se perderá cosas.
Brent Rockwood
17

También tenga en cuenta que el observador del sistema de archivos no es confiable en los archivos compartidos. Particularmente si el recurso compartido de archivos está alojado en un servidor que no es de Windows. FSW no debe usarse para nada crítico. O debe usarse con una encuesta ocasional para verificar que no se haya perdido nada.

frío
fuente
3
¿Microsoft ha reconocido que no es confiable en archivos compartidos que no son de Windows? Ciertamente estamos experimentando esto de primera mano desde que cambiamos de un recurso compartido de Windows a un recurso compartido SMB basado en Linux.
Sean
1
No que yo supiese. Y estoy seguro de que simplemente sería un juego de culpa entre los diferentes proveedores.
chilltemp
1
Hemos experimentado problemas con el observador del sistema de archivos en unidades mapeadas. Si el mapa se desconecta y luego se vuelve a conectar, el observador de archivos ya no genera cambios. Se resuelve fácilmente pero sigue siendo un ataque contra el observador del sistema de archivos en mi humilde opinión.
Richard Dorman
11

Personalmente, he usado FileSystemWatcherun sistema de producción y ha funcionado bien. En los últimos 6 meses, no ha tenido un solo problema las 24 horas del día, los 7 días de la semana. Está monitoreando una sola carpeta local (que se comparte). Tenemos un número relativamente pequeño de operaciones de archivos que tiene que manejar (10 eventos disparados por día). No es algo de lo que deba preocuparme. Lo usaría nuevamente si tuviera que rehacer la decisión.

Jim
fuente
7

Actualmente uso el FileSystemWatcheren un archivo XML que se actualiza en promedio cada 100 milisegundos.

He descubierto que, siempre que FileSystemWatcheresté configurado correctamente, nunca debería tener problemas con los archivos locales .

No tengo experiencia en la observación remota de archivos y recursos compartidos que no sean de Windows.

Consideraría que sondear el archivo es redundante y no vale la pena la sobrecarga a menos que desconfíe inherentemente FileSystemWatchero haya experimentado directamente las limitaciones que todos los demás aquí han enumerado (recursos compartidos que no son de Windows y observación remota de archivos).

Persistencia de la visión
fuente
5

Yo iría con las encuestas.

Los problemas de red hacen FileSystemWatcherque no sea confiable (incluso cuando se sobrecarga el evento de error).

azulado
fuente
5

Me he encontrado con problemas al usar FileSystemWatcheren recursos compartidos de red. Si está en un entorno puro de Windows, puede que no sea un problema, pero estaba viendo un recurso compartido NFS y dado que NFS no tiene estado, nunca hubo una notificación cuando el archivo que estaba viendo cambió.

Jon Norton
fuente
Me encontré con el mismo problema, pero fue inesperado para mí ya que FileSystemWatcher estaba en el mismo servidor de Windows que comparte la carpeta con NFS. El hecho de compartir una carpeta con NFS hace que el sistema de archivos no vea los archivos creados utilizando el recurso de forma remota (es decir, desde un Linux que asigna el recurso compartido), mientras que si escribo un archivo en la misma carpeta bajo supervisión, se activa el sistema de archivos. parece que el servidor NFS escribe archivos usando una capa inferior y la capa API que dispara el sistema de archivos no está activada, ¿alguien tiene más información?
Mosè Bottacini
3

Tuve algunos problemas importantes con FSW en las unidades de red: la eliminación de un archivo siempre generaba el evento de error, nunca el evento eliminado. No encontré una solución, así que ahora evito el FSW y uso el sondeo.

Los eventos de creación, por otro lado, funcionaron bien, por lo que si solo necesita observar la creación de archivos, puede optar por la FSW.

Además, no tuve ningún problema en las carpetas locales, sin importar si las compartía o no.

Treb
fuente
3

Volviendo del método de evento lo más rápido posible, usando otro hilo, resolvió el problema para mí:

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    Task.Run(() => MySubmit(e.FullPath));
}
derrame
fuente
2

Usar FSW y encuestas es una pérdida de tiempo y recursos, en mi opinión, y me sorprende que los desarrolladores experimentados lo sugieran. Si necesita usar el sondeo para verificar si hay "fallas de FSW", entonces, naturalmente, puede descartar FSW por completo y usar solo el sondeo.

Actualmente, estoy tratando de decidir si usaré FSW o sondeo para un proyecto que desarrolle. Al leer las respuestas, es obvio que hay casos en los que FSW cubre las necesidades a la perfección, mientras que otras veces, necesita encuestas. Desafortunadamente, ninguna respuesta ha tratado la diferencia de rendimiento (si la hay), solo los problemas de "confiabilidad". ¿Hay alguien que pueda responder esa parte de la pregunta?

EDITAR: el punto de nmclean para la validez del uso de FSW y encuestas (puede leer la discusión en los comentarios, si está interesado) parece ser una explicación muy racional de por qué puede haber situaciones en las que usar tanto FSW como encuestas es eficiente. Gracias por arrojar luz sobre eso para mí (y para cualquier otra persona que tenga la misma opinión), nmclean .

ThunderGr
fuente
1
¿Qué sucede si desea responder a los cambios de archivos lo más rápido posible? Si realiza una encuesta una vez por minuto, por ejemplo, es posible que tenga un retraso de hasta 1 minuto entre el cambio de un archivo y la recuperación de su aplicación. El evento FSW probablemente se desencadenaría mucho antes de eso. Entonces, al usar ambos, maneja los eventos con el menor retraso posible, pero también recoge los eventos perdidos si los hay.
rom99
@ rom99 Exactamente mi punto. Si el FSW no es confiable en los casos en que necesita una respuesta rápida, no tiene sentido usarlo, ya que tendrá casos en los que no habrá una respuesta rápida, por lo tanto, su aplicación no será confiable. Encuesta en intervalos más cortos, en un hilo, sería lo que necesita hacer. Al hacer ambas cosas , significa que tiene tolerancia en los tiempos de respuesta que cubre el sondeo, entonces, ¿por qué no usar solo el sondeo?
ThunderGr
55
@ThunderGr "por lo tanto, su aplicación no será confiable". - En muchos casos, la velocidad no es un requisito previo para la confiabilidad. El trabajo debe hacerse, pero puede esperar un tiempo. Si combinamos un sondeo lento y confiable con un FSW rápido y poco confiable , obtenemos una aplicación que siempre es confiable ya veces rápida, que es mejor que confiable y nunca rápida. Podemos eliminar FSW y lograr el mismo tiempo de respuesta máximo haciendo un sondeo constante, pero esto es a expensas de la capacidad de respuesta del resto de la aplicación, por lo que solo debe hacerse si se requiere una respuesta inmediata.
nmclean
2
Ahora, ¿por qué lo anterior es un argumento pobre? Porque, aunque todavía necesitamos acceso al disco, lo necesitamos menos . Del mismo modo, puede sondear menos. El hecho de que aún verifiquemos todos los archivos no significa que la carga de trabajo sea la misma. Su afirmación, "el sondeo es costoso en tiempo de CPU con FSW o no", es falso . Al descargar la preocupación de "inmediatez" a FSW, podemos cambiar el sondeo a una tarea inactiva y de baja prioridad, de modo que la ocupación de la aplicación en cualquier momento dado se reduzca drásticamente mientras se proporciona el "tratamiento" de la inmediatez. Simplemente no puede lograr el mismo equilibrio solo con encuestas.
nmclean
9
@nmclean Gracias por tomarse el tiempo y la energía para aclarar esto de la manera que lo hizo. Cuando lo pones de esa manera, seguramente tiene mucho más sentido. Al igual que hay veces que una memoria caché no es adecuada para su problema específico, la FSW (cuando no es confiable) puede no ser adecuada. Resulta que tenías razón todo el tiempo. Lamento que me haya tomado tanto tiempo obtenerlo.
ThunderGr
1

Solución de trabajo para trabajar con crear evento en lugar de cambio

Incluso para copiar, cortar, pegar, mover.

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

Solución para este observador de archivos mientras el evento de cambio de atributo de archivo utiliza almacenamiento estático

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

Esta es una solución alternativa para este problema de evento de activación múltiple.

Mark Macneil Bikeio
fuente
0

Yo diría que use el sondeo, especialmente en un escenario TDD, ya que es mucho más fácil burlarse de la presencia de archivos o de otra manera cuando se desencadena el evento de sondeo que confiar en el evento fsw más "no controlado". + a eso de haber trabajado en varias aplicaciones plagadas de errores de FSW.

usuario2819502
fuente