2010-07-14 36 views
13

Estoy escribiendo una herramienta que supervisa un directorio de red y se está ejecutando desde una máquina con Windows Server 2008, el evento OnChanged para FileSystemWatcher se activa correctamente desde archivos colocados en la unidad de red por cualquier computadora que sin usar Windows 7, por alguna razón, si la cantidad de archivos copiados es más de 19 en una computadora con Windows 7 (a la vez), entonces no se disparan los eventos, aunque funciona si los archivos se realizan individualmente. ¿Hay alguna solución para esto o solo es así como se comporta el kernel de Windows 7 con los eventos de FSW?FileSystemWatcher y Windows 7

Solo para aclarar, funciona para miles de archivos cuando se copia desde una máquina XP. (El software todavía está en la máquina servidor 2008).

Respuesta

22

De MSDN:

El sistema operativo Windows notifica a su componente de cambios en los archivos en una memoria intermedia creada por el FileSystemWatcher. Si hay muchos cambios en poco tiempo, el buffer puede desbordarse. Esto hace que el componente pierda de vista los cambios en el directorio, y solo proporcionará una notificación general. Aumentar el tamaño del búfer con la propiedad InternalBufferSize es costoso, ya que proviene de una memoria no paginada que no se puede intercambiar en el disco, por lo que debe mantener el búfer lo suficientemente pequeño como para no perder ningún cambio de archivo. Para evitar un desbordamiento de búfer, use las propiedades NotifyFilter y IncludeSubdirectories para que pueda filtrar las notificaciones de cambios no deseados.

Si aumentar el tamaño del búfer no es suficiente y no puede controlar cuántos archivos están desencadenando eventos a la vez, debería agregar un sondeo adicional.

Ver también esta pregunta relacionada:

FileSystemWatcher does not work properly when many files are added to the directory at the same time…

Actualización:

Puede ser tentador simplemente aumentar el tamaño del búfer, pero esto debe hacerse con cuidado. De hecho, hay una limitación de 64k cuando se trata de acceso a la red. La clase FileSystemWatcher está utilizando la función API de Windows ReadDirectoryChangesW debajo de la cual tiene este límite:

ReadDirectoryChangesW falla con ERROR_INVALID_PARAMETER cuando la longitud del búfer es mayor que 64 KB y la aplicación monitoriza un directorio a través de la red. Esto se debe a una limitación de tamaño de paquete con los protocolos subyacentes de uso compartido de archivos.

Si desea obtener una comprensión más profunda sobre el costo de modificar el tamaño del búfer que debe tener una mirada en el puesto de Walter Wang de Microsoft aquí:

FileSystemWatcher across the network (post completo citado más adelante)

siento que la documentación de FileSystemWatcher.InternalBufferSize no declaró muy claro sobre el tamaño de la memoria intermedia al supervisar la red ruta. Se recomienda que no exceda 64K al supervisar la ruta de la red.

FileSystemWatcher es básicamente una.Contenedor de red para Win32 API ReadDirectoryChangesW. Para usar ReadDirectoryChangesW, cree y especifique un búfer que el sistema operativo poblará con los cambios. Sin embargo, lo que no se menciona en la documentación ReadDirectoryChangesW (pero se insinúa en los docs FileSystemWatcher) es que el sistema de archivos crea un núcleo interno buffer para almacenar la información de cambio temporalmente hasta que tenga la oportunidad de actualización el buffer del usuario. El tamaño de el buffer del kernel que se creó es del mismo tamaño que se especifica en ReadDirectoryChangesW y se creó en la memoria agrupada no paginada. Cada vez que se crea un FileSystemWatcher/ ReadDirectoryChangesW/ , también se crea un nuevo búfer de kernel .

Las piscinas de memoria de núcleo (paginados y no paginada) se reservan en el espacio de direcciones del sistema para los controladores de dispositivos y otros componentes del núcleo de usar. Crean y contraen dinámicamente como necesario. El tamaño actual de las agrupaciones se puede ver fácilmente yendo a la pestaña Rendimiento del Administrador de tareas . Las agrupaciones crecerán dinámicamente hasta que alcancen un valor máximo de que se calcula en el momento del arranque y depende de los recursos del sistema disponibles (en su mayoría RAM). No desea querer alcanzar este valor máximo o de lo contrario varios servicios del sistema y controladores comenzarán a fallar. Sin embargo, este valor máximo calculado no es fácilmente disponible. Para determinar el tamaño máximo de grupo de , debe utilizar un depurador kernel . Si está interesado en más información sobre el sistema agrupaciones de memoria, le recomiendo que consulte el Capítulo 7 en el libro MSPress Dentro de Windows 2000 de Solomon y Russinovich.

Teniendo esto en cuenta, no hay ninguna recomendación sobre qué tamaño de buffers puede usar. El tamaño actual y máximo de de las agrupaciones del sistema van a variará de cliente a cliente. Sin embargo, probablemente no debería ir más de 64k para cada FileSystemWatcher/ ReadDirectoryChangesW buffer. Esto se basa en el hecho de que existe una limitación de 0k 64k con acceso a la red como documentada en ReadDirectoryChangesW. Pero al final va a tener para probar la aplicación en una variedad de los sistemas de destino esperados para que pueda sintonizar su memoria intermedia.

Hay una sobrecarga asociada con .Net aplicaciones y me imagino que un programa Win32 ReadDirectoryChangesW podría ser capaz de lograr un mejor rendimiento con el mismo tamaño del búfer. Sin embargo, con los cambios de archivos muy rápidos y numerosos, desbordamientos de búfer habrá inevitable y el desarrollador va a tener que manejar el caso cuando se produce un rebasamiento como manualmente enumerar el directorio para detectar los cambios.

En conclusión, FileSystemWatcher y ReadDirectoryChangesW son un mecanismo de ligero cambio de archivos de detección que va a tener sus limitaciones . Cambio de Revistas es otro mecanismo que nos considerar una solución de peso medio, pero aún tendrían limitaciones:

http://msdn.microsoft.com/en-us/library/aa363798%28VS.85%29.aspx

soluciones de gran peso serían escribir un filtro de sistema de archivos dedicado conductor que se sienta en el sistema de archivos apila y supervisa los cambios del sistema de archivos . Por supuesto, este sería el enfoque más complejo de . La mayoría de los virus escáneres, software de copia de seguridad y archivo utilidades de monitoreo del sistema como filemon (www.sysinternals.com) implementan un controlador de filtro.

Espero que la explicación anterior le ayude a comprender la causa raíz del problema que está experimentando. Responda y avísenos si necesita más información. Gracias.

+0

Sólo una pequeña adición: el tamaño de búfer predeterminado es 8192. –

4

Después de muchos intentos de usar el FileSystemWatcher he renunciado a él. No disparará los eventos correctamente, en el momento equivocado, el tipo incorrecto. Honestamente, creo que es una de las peores clases en el framework .net. Siempre he terminado escribiendo mi propia clase que toma un System.Timer y después de transcurridos x milisegundos, comprueba los directorios, los archivos manualmente. Sí, lleva más trabajo y sí, puede ser un PITA leve, pero una vez que lo haya escrito, puede usarlo donde quiera. Me gustaría que FileSystemWatcher funcionara como se anuncia, pero nunca lo encontré para hacerlo.

+0

Estoy de acuerdo que 'FileSystemWatcher', obviamente, no es apropiado en todas las situaciones. Sin embargo, una capacidad que ofrece, que es difícil de hacer con una simple enumeración de directorios, es la detección de renombrados de archivos. Se puede hacer (utilizando comparaciones de propiedades de archivo, heurística, sumas MD5, etc.), pero es una molestia. – stakx

+0

@stakx, eso es muy cierto, nunca he intentado verificar los cambios en el nombre del archivo. Me acabo de quemar tanto esa clase que nunca la uso. – Justin

2

La mayoría de las veces cuando se desencadena un evento FileSystemWatcher, ignoro los archivos que el objeto está pasando porque esta lista puede estar incompleta.

Simplemente rastreo el directorio que el objeto FileSystemWatcher está monitoreando y realizo un escaneo manual para encontrar los archivos que podrían no estar en el buffer de FileSystemWatcher. No es realmente elegante, pero se asegura de que no te pierdas ningún archivo.

+0

que parece una cuestión totalmente separada de la inconsistencia de la que habla el OP. – Chad

+0

@Chad: ¿Cómo parece esto totalmente sin relación? Diría que suena exactamente como un método para solucionar el problema del OP. –

+0

porque el OP dice que el evento no se dispara en absoluto. Laurens sugiere que * cuando se desencadena el evento * verifican manualmente el directorio, pero si el evento nunca se dispara en primer lugar, el OP no puede hacer esto. Por lo tanto, el comentario de Laurens no es sobre el mismo problema que está viendo el OP. Al menos, así es como leo la pregunta del OP en relación con el comentario de Laurens. – Chad

0

Esta es una clase realmente no fiable, cuando los archivos están por encima de un cierto umbral He tenido eventos disparando unas 7 veces en la copia inicial y luego cuando el cuadro de diálogo de transferencia de archivos se realiza otros 7 eventos, este problema aparece en todos los OS que soportan el FSW. Aunque Windows 7 (aún no se ha probado su vista) solo acepta archivos uno por uno o 19 a la vez, y si dejo archivos de una máquina XP en la unidad de red, puedo leer miles de archivos a la vez sin problemas. Esto puede ser solo un cambio en ReadDirectoryChangesW de XP a 7. Pasados ​​19 archivos. No pude obtener CUALQUIER evento para disparar, así que supongo que se convertirá en una "característica" de mi herramienta por ahora. Si alguien tiene alguna otra información, no dude en contribuir.

-1

Si utiliza el MacOSX + + Parallels Desktop de Windows, Su código no funciona, Debido a su propiedad es FileSystemWatcher.Path destino a la ruta de Mac, es una ruta UNC, no es compatible!

enter image description here