2011-07-12 9 views
6

Tengo una aplicación que funciona muy bien para procesar archivos que aterrizan en un directorio en mi servidor. El proceso es:Procesar archivos al mismo tiempo que llegan en C#

1) check for files in a directory 
2) queue a user work item to handle each file in the background 
3) wait until all workers have completed 
4) goto 1 

Esto funciona muy bien y nunca se preocupan por el mismo archivo que se está procesando dos o varios hilos que se dio lugar para el mismo archivo. Sin embargo, si hay un archivo que lleva demasiado tiempo procesar, el paso 3 se cuelga en ese archivo y contiene todo el otro procesamiento.

Así que mi pregunta es, ¿cuál es el paradigma correcto para engendrar exactamente un hilo por cada archivo que necesito procesar, sin bloquear si un archivo tarda demasiado? Consideré FileSystemWatcher, pero es posible que los archivos no se puedan leer de inmediato, por lo que continuamente miro todos los archivos y genero un proceso para cada uno (que se cerrará inmediatamente si el archivo está bloqueado).

¿Debo eliminar el paso n. ° 3 y mantener una lista de archivos que ya he procesado? Eso parece desordenado y la lista crecerá mucho con el tiempo, así que sospecho que hay una solución más elegante.

+0

¿Qué sucede con un archivo después de que se procesa? ¿permanece en el mismo directorio? eliminado? ¿movido? Además, ¿están los archivos volcados en el directorio del servidor de forma consistente con la misma extensión? – gangelo

+0

No entiendo cómo su proceso, como se menciona anteriormente, impide que los archivos se procesen dos veces. –

+0

Después de procesar un archivo, se elimina en el paso n. ° 2, por lo que una vez completado el paso n. ° 3, todos los archivos de la carpeta se procesarán y no se han procesado previamente. – powlette

Respuesta

6

Le sugiero que mantenga una lista de los archivos que está procesando actualmente. Haga que el hilo se elimine de esta lista cuando termine el hilo. Al buscar nuevos archivos, excluya aquellos en la lista actualmente en ejecución.

+0

¿Cómo se hace un seguimiento de qué archivos se han procesado después de que se han eliminado de la cola de hilos? – gangelo

+0

Él ya tiene ese problema, así que supongo que esto ya está resuelto, por ejemplo, al eliminar el archivo al final del proceso. –

+0

Sí, esto es esencialmente lo que estaba pensando; solo esperaba que existiera un paradigma existente entre productores y consumidores que fuera probado y verdadero en lugar de hacerlo yo mismo. Gracias. – powlette

3

Mueva los archivos a un directorio de procesamiento antes de iniciar los subprocesos. Luego puedes disparar y olvidar los hilos y cualquier administrador puede ver de un vistazo lo que está pasando.

+0

Esto supone que incluso puede hacer esto en el servidor, pero me gusta esta idea porque sabes qué archivos deben procesarse/se/han procesado en virtud de que están en sus respectivos directorios. – gangelo

3

Engendrar un hilo por artículo para procesar casi nunca es un buen enfoque. En su caso, cuando la cantidad de archivos supere varios cientos de un hilo por archivo, el rendimiento de las aplicaciones será bastante malo y con el proceso de 32 bits se agotará el espacio de direcciones.

La solución de lista de Dark Falcon es bastante simple y coincide con su algoritmo. De hecho, utilizaría queue (likel ConcurrentQueue - http://msdn.microsoft.com/en-us/library/dd267265.aspx) para poner elementos a procesar en un lado (es decir, en base a exploraciones periódicas del vigilante de archivos) y seleccionar elementos para procesarlos por uno o varios hilos del otro lado. Por lo general, desea un número menor de subprocesos (es decir, 1-2 veces el número de CPU para la carga intensiva de la CPU).

Considere también el uso de la Biblioteca de tareas paralelas (como Parallel.ForEach - http://msdn.microsoft.com/en-us/library/dd989744.aspx) para tratar múltiples hilos.

Para minimizar el número de archivos a manipular, mantendría una lista persistente (es decir, archivo de disco) ya procesada: ruta de archivo + última fecha de modificación (a menos que pueda obtener esta información de otra fuente).

1

Mis dos preguntas principales serían:

  1. ¿Cuáles son el tamaño de los archivos?
  2. ¿Con qué frecuencia aparecerán los archivos?

Dependiendo de su respuesta allí, yo podría ir con el siguiente algoritmo productor-consumidor:

  1. Utilice un FileSystemWatcher para ver que hay actividad en el directorio que está supervisando
  2. Cuando se produce actividad, comience a sondear "ligeramente"; eso es probar cada archivo disponible para ver si no está bloqueado (es decir, intente abrir w/privilegios de escritura usando un método de extensión simple IsLocked que se prueba mediante un intento ...captura); si 1 o más archivos no son gratuitos, configure un temporizador para que se apague en cierta cantidad de tiempo (más tiempo si espera menos archivos más grandes, más corto si es más pequeño y/o más frecuente) para probar nuevamente los archivos
  3. Tan pronto como vea eso un archivo es gratuito, trátelo (es decir, muévalo a otra carpeta, coloque un elemento en una cola concurrente, haga que sus hilos de consumo procesen la cola, archive el archivo/resultados).
  4. Tiene algún tipo de mecanismo de persistencia como menciona Alexei (es decir, disco/base de datos) para poder recuperar su procesamiento donde lo dejó en caso de falla del sistema.

Creo que esta es una buena combinación de comportamiento de bloqueo y bajo uso de la CPU. Pero mida sus resultados antes y después. Yo recomiendo usar ThreadPool y tratar de mantener las discusiones de bloqueo (es decir, tratar de asegurarse de hilo reutilización por parte de no bloqueo haciendo algo como Thread.Sleep)

Notas:

  1. Base el número de hilos que procesan archivos sobre la cantidad de CPU y núcleos disponibles en la máquina; también considere la carga del servidor
  2. FileSystemWatcher puede ser meticuloso; asegúrese de que se ejecute desde la misma máquina que está monitoreando (es decir, que no esté mirando un servidor remoto), de lo contrario tendrá que reiniciar la conectividad de vez en cuando.
  3. Definitivamente no generaría un proceso diferente por archivo; múltiples hilos deberían ser suficientes; reutilizar hilos es lo mejor. Los procesos de desove son una operación muy costosa y los hilos de desove son costosos. Alexei tiene buena información sobre la Biblioteca paralela de tareas; usa el ThreadPool.
Cuestiones relacionadas