2010-03-22 8 views
7

Tengo esta aplicación que recurrirá todas las carpetas en un directorio determinado y buscará PDF. Si se encuentra un archivo PDF, la aplicación contará sus páginas con ITextSharp. Hice esto mediante el uso de un hilo para escanear recursivamente todas las carpetas para PDF, y luego, si se encuentra PDF, esto se pondrá en cola para el grupo de subprocesos. El código es el siguiente:¿Cómo saber si todo el hilo del conjunto de hilos ya está hecho con sus tareas?

//spawn a thread to handle the processing of pdf on each folder. 
       var th = new Thread(() => 
       { 
        pdfDirectories = Directory.GetDirectories(pdfPath); 
        processDir(pdfDirectories); 
       }); 
       th.Start(); 



private void processDir(string[] dirs) 
     { 
      foreach (var dir in dirs) 
      { 
       pdfFiles = Directory.GetFiles(dir, "*.pdf"); 
       processFiles(pdfFiles); 

       string[] newdir = Directory.GetDirectories(dir); 
       processDir(newdir); 
      } 
     } 



private void processFiles(string[] files) 
     { 
      foreach (var pdf in files) 
      { 
       ThreadPoolHelper.QueueUserWorkItem(
        new { path = pdf }, 
        (data) => { processPDF(data.path); } 
        ); 
      } 
     } 

Mi problema es, ¿cómo sé que ese hilo de la piscina mensaje ha terminado de procesar todos los elementos en cola para que pueda avisar al usuario de que la aplicación se realiza con la tarea prevista?

Respuesta

4

Generalmente haria algo como esto teniendo una variable de contador. Para cada elemento de trabajo que hace cola en el ThreadPool agregue uno a la variable de contador. Luego, cuando se procese, disminuirá la variable de contador.

Asegúrese de que lo haga el incremento y decremento a través de los métodos de la clase Interlocked ya que esto garantizará que se hacen las cosas de una manera segura para los subprocesos.

Una vez que los éxitos de venta libre cero que pudiera bandera que las tareas se han completado mediante un ManualResetEvent

Si usted tiene acceso a .NET 4, puede utilizar la nueva clase CountdownEvent hacer una cosa similar.

+0

He hecho una lógica similar a esto. Solo utilicé ThreadPool.GetAvailableThreads. Configuré MaxThreads que las agrupaciones deberían estar usando por 20. Así que, al final de la tarea, verifiqué si los hilos disponibles son iguales al máximo que establecí. Desafortunadamente esto falla. Investigaré sobre ese evento de reinicio manual. –

+1

@mcxiand: No puede usar los contadores ThreadPool porque otro código (lib) podría crear subprocesos y el TP los está reciclando/eliminando. –

+0

@Henk Holterman: ¿Es así? Por lo que entendí es que, ThreadPool se pondrá en cola de la tarea mediante el método QueueUserWorkItem. ¿Puedes dar más detalles sobre tu comentario? sería muy apreciado. –

2

1) ¿Cómo saber si todos los hilos están terminados?

Tendrá que dejar que los Hilos hacen su propio check-in/check-out, poniendo entre paréntesis el código entre:

Interlocked.Increment(ref jobCounter); 
// your code 
Interlocked.Decrement(ref jobCounter); 

Si esto puede confundir a sus delegados anónimos demasiado, entonces sólo tiene que utilizar métodos de contenedor. Probablemente también deba agregar el manejo de excepciones.

El enfoque entrelazado todavía aletea el problema de esperar que se convierta en 0, un ciclo con Sleep() es una solución débil pero en este caso viable.

2) Estás iniciando los hilos en un andador de árbol recursivo. Tenga cuidado, probablemente esté creando demasiados y perjudicará el rendimiento.

+0

solo tengo un hilo para hacer la recursión y cola cada archivo pdf encontrado en cada carpeta por el hilo –

+0

OK, es más lineal. Y a partir de los comentarios aceleras MaxThreads. Todavía requiere afinar y cambiar MaxThreads es un mazo. –

+0

He controlado MaxThreads porque en este hilo, estoy actualizando el control de UI usando BeginInvoke. La IU se congelará si hay muchos subprocesos en ejecución. ¿Alguna recomendación? –

Cuestiones relacionadas