Pregunta

Duplicar: Cómo coger excepciones a una ThreadPool.QueueUserWorkItem


Estoy haciendo cola varios delegados en el .NET ThreadPool para un gran número de interacción remota independiente llamadas con las que ellos mismos llaman a múltiples bases de datos y otros recursos fuera de línea. Por estas Queuing pide a la ThreadPool puedo ejecutarlos al mismo tiempo y minimizar la latencia global.

private void CompleteAndQueuePayLoads(IEnumerable<UsagePayload> payLoads)
{
    List<WaitHandle> waitHndls = new List<WaitHandle>();
    foreach (UsagePayload uPyLd in payLoads)
    {
        ManualResetEvent txEvnt = new ManualResetEvent(false);
        UsagePayload uPyLd1 = uPyLd ;
        ThreadPool.QueueUserWorkItem(
            delegate
                {
                    if (!uPyLd1 .IsComplete)
                        // IEEDAL.GetPayloadReadings is long running DB call
                        try { IEEDAL.GetPayloadReadings(uPyLd1 ); }
                        catch (IEEAccessException iX)
                        {
                            log.Write(log.Level.Error,
                                  "IEEWSDAL.CompleteAndQueuePayLoads " + 
                                   " Delegate Failed " +
                                  iX.Message, iX);
                            txEvnt.Set();
                            throw;  // this causes parent thread to crash!
                            // was going to try Thread.Abort next ...
                            // Thread.CurrentThread.Abort();
                        }
                    UsageCache.PersistPayload(uPyLd1 );
                    SavePayLoadToProcessQueueFolder(uPyLd1 );
                    txEvnt.Set();
                });
        waitHndls.Add(txEvnt);
    }
    util.WaitAll(waitHndls.ToArray()); //To waitone on > 64 waithandles
}

Sin embargo, todo el lote debe ser manejada de forma transaccional, es decir, la salida de la rosca padre tiene que ser permitido solamente para continuar si todas las discusiones niño tuvieron éxito. Yo había codificado el hilo hijo para lanzar una excepción personalizada cuando fracasó, pero he descubierto que esto hace que el hilo se bloquee padres, ya que estas excepciones no pueden ser "atrapados" en el hilo de los padres ...

He leído acerca de la UnHandledExceptionEvent tirar por el CLR cuando esto sucede, pero necesito de "manejar" esta excepción en el método en el que estos procesos hijo están en cola y engendraron, para controlar el procesamiento aguas abajo inmediata basada en el éxito de teh threeads niño ... ¿Cómo hago para esto?

¿Fue útil?

Solución

Lo hago mucho en mi proyecto actual. El enfoque que tomé fue para hacer mi propio programador que toma el delegado, lo añade a mi propia cola, y los ejecuta para manejar la sincronización al final, etc.

El "truco" que he utilizado en este caso es la de no llamar al delegado directamente en el grupo de subprocesos, sino más bien llamar a un método en mi planificador que envuelve el delegado y maneja la excepción más gracia. De esta manera, la, llamada real método interno se trata siempre de una manera apropiada (para mí) de forma.

Cuando ocurre una excepción, mi programador es notificado y se detiene la programación de las tareas futuras (que es un buen bono), pero también se encarga de decirle a la persona que llama que había una sola excepción.

Otros consejos

Si el hilo falla, podría marcar que al menos un fallo se ha producido en el interior de una variable local de la función CompleteAndQueuePayLoads, y añadir una excepción / fracasos variables para ser examinados más adelante.

Es posible buscar en las extensiones de la biblioteca en paralelo para 3.5. Puede utilizar Parallel.Invoke en su bloque de código para hacer exactamente lo que intenta realizar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top