FileSystemWatcher frente a sondeo para ver los cambios de archivos

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

Sería el FileSystemWatcher o el sondeo en un temporizador sería la mejor opción. He usado ambos métodos en el pasado, pero no exhaustivamente.

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

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

Editar: si tiene una IU, 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.

El mayor problema que he tenido es que faltan archivos cuando el búfer se llena. Fácil como un pastel para arreglar, solo aumenta el buffer. Recuerde que contiene los nombres y eventos de los archivos, por lo tanto, increméntelos a la cantidad esperada de archivos (prueba y error). Utiliza memoria que no se puede paginar, por lo que podría obligar a otros procesos a la página si la memoria baja.

Aquí está el artículo de MSDN en el búfer: FileSystemWatcher .. ::. InternalBufferSize Property

Por MSDN:

Aumentar el tamaño del búfer es costoso, ya que proviene de una memoria no paginada que no puede intercambiarse 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 al mismo tiempo. Funciona bien y nunca pierde un archivo.

También leemos todos los archivos antes de comenzar a procesar uno solo … 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 locking de archivos genero un proceso que espera a que el archivo se desbloquee esperando un segundo, luego dos, luego cuatro, etcétera. Nunca encuestamos Esto ha estado en producción sin error durante aproximadamente dos años.

El FileSystemWatcher también puede perder cambios durante las horas punta, si la cantidad de cambios en la cola se desborda del búfer provisto. Esto no es una limitación de la clase .NET per se, sino de la infraestructura Win32 subyacente. En nuestra experiencia, la mejor manera de minimizar este problema es eliminar 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 las unidades montadas de Novell.

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

También tenga en cuenta que el vigilante del sistema de archivos no es confiable en recursos compartidos de archivos. 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 se debe usar con una encuesta ocasional para verificar que no se haya perdido nada.

Personalmente, he usado FileSystemWatcher en un sistema de producción, y funcionó bien. En los últimos 6 meses, no ha tenido un solo inconveniente 24×7. Está monitoreando una única carpeta local (que se comparte). Tenemos un número relativamente pequeño de operaciones de archivos que debe manejar (10 eventos activados por día). No es algo de lo que me haya tenido que preocupar. Lo usaría nuevamente si tuviera que rehacer la decisión.

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

Descubrí que, siempre que FileSystemWatcher esté configurado correctamente, nunca deberías tener problemas con los archivos locales .

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

Consideraría que el sondeo del archivo es redundante y no vale la pena sobrecargarlo a menos que desconfíe intrínsecamente de FileSystemWatcher o haya experimentado directamente las limitaciones que todos los demás han enumerado aquí (recursos compartidos que no son de Windows y visualización remota de archivos).

Me gustaría ir con las encuestas.

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

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

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

Por otro lado, los eventos de creación funcionaron bien, por lo que si solo necesita ver la creación de archivos, puede ir a la FSW.

Además, no tuve ningún problema en las carpetas locales, sin importar si se compartieron o no.

El uso tanto de FSW como de sondeo 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 en el FSW”, entonces, naturalmente, puede descartar el FSW por completo y usar solo el sondeo.

Actualmente estoy tratando de decidir si usaré FSW o un sondeo para un proyecto que desarrolle. Al leer las respuestas, es obvio que hay casos en los que FSW cubre las necesidades perfectamente, mientras que otras veces, necesita un sondeo. Lamentablemente, ninguna respuesta se ha ocupado realmente de la diferencia de rendimiento (si hay alguna), solo con los problemas de “fiabilidad”. ¿Hay alguien que pueda responder esa parte de la pregunta?

EDITAR: El punto de nmclean para la validez del uso tanto de FSW como de sondeo (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 polling es eficiente. Gracias por arrojar luz sobre eso para mí (y para cualquiera que tenga la misma opinión), nmclean .

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

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 vigilante de archivo 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 desencadenante múltiple.

Yo diría usar encuestas, 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 votación que confiar en el evento fsw más “incontrolado”. + a eso haber trabajado en una serie de aplicaciones que estaban plagadas de errores fsw.

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

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