2011-08-10 11 views
5

Estaba trabajando en la inclusión de subprocesos en mi código azul para poner cosas en una cola. Para hacer esto usé http://www.microsoft.com/download/en/details.aspx?id=19222 como referencia.Tarea.Espere en Continuar cuando Acción

mi código para poner en cola múltiples mensajes se parece a esto:

public void AddMessagesAsync(IEnumerable<IQueueMessage> messages, string queue = null, TimeSpan? timeToLive = null) 
{ 
    //check if we need to switch queues 
    if (!String.IsNullOrEmpty(queue)) 
    { 
    SetCurrent(queue); 
    } 

    //setup list of messages to enqueue 
    var tasks = new List<Task>(); 
    Parallel.ForEach(messages, current => { 
    if (timeToLive.HasValue) 
    { 
     //create task with TPL 
     var task = Task.Factory.FromAsync(Current.BeginAddMessage, Current.EndAddMessage, Convert(current), timeToLive.Value, tasks); 
     //setup continuation to trigger eventhandler 
     tasks.Add(task.ContinueWith((t) => AddMessageCompleted(t))); 
    } 
    else 
    { 
     //create task with TPL 
     var task = Task.Factory.FromAsync(Current.BeginAddMessage, Current.EndAddMessage, Convert(current), tasks); 
     //setup continuation to trigger eventhandler 
     tasks.Add(task.ContinueWith((t) => AddMessageCompleted(t))); 
    } 
    }); 

    //setup handler to trigger when all messages are enqueued, a we are blocking the thread over there to wait for all the threads to complete 
    Task.Factory.ContinueWhenAll(tasks.ToArray(), (t) => AddMessagesCompleted(t));    
} 

private void AddMessagesCompleted(Task[] tasks) 
{ 
    try 
    { 
    //wait for all tasks to complete 
    Task.WaitAll(tasks); 
    } 
    catch (AggregateException e) 
    { 
    //log the exception 
    var ex = e; 
    //return ex; 
    } 

    if (AddedMessages != null) 
    { 
    AddedMessages(tasks, EventArgs.Empty); 
    } 
} 

Ahora mi pregunta es acerca de la Task.Wait en la continuación (que es según el documento proporcionado por MS). Parece un poco extraño esperar hilos donde ya sabes que se han completado ¿verdad? la única razón que me puedo imaginar es burbujear los errores y procesarlos. ¿Me estoy perdiendo de algo?

Respuesta

4

Task.WaitAll() arrojará un AggregateException cuando se haya cancelado al menos una de las instancias de la tarea -o bien- se haya producido una excepción durante la ejecución de al menos una de las instancias de la tarea.

ContinueWhenAll() no va a lanzar esta excepción y su simplemente iniciar su última tarea cuando todo termina cancelados o no, etc.

+0

supongo que estamos de acuerdo en mi suposición, entonces? –

+0

@Didier Sí, olvida esa parte en mi respuesta :) – Skomski

2

En primer lugar, me he dado cuenta de que está utilizando List<T> con Parallel.ForEach que no es seguro para subprocesos, se debe reemplazar con una colección concurrente, por ejemplo: ConcurrentQueue<T>.

En cuanto WaitAll vs ContinueWhenAll, WaitAll tirará Si se abre alguna de las tareas, por lo que el código anterior es para validar todas las tareas que han completado con éxito, puede hacer lo mismo si pasa ContinuationOptions parámetro para ContinueWhenAll como OnlyRanToCompeletion por lo que la la tarea de continuación se programará solo si todas las tareas se completaron correctamente.

+0

¡Hola! gracias por el puntero sobre la seguridad del hilo ... salvavidas definitivo. –