2012-03-06 14 views
7

tengo un método con la siguiente estructura:composición de tareas y gestión de errores con TPL

public Task InitializeAsync() 
{ 
    var taskCompletionSource = new TaskCompletionSource<bool>(); 

    Task firstTask = ...; 

    // secondTask calls taskCompletionSource.TrySetResult(true) once it considers itself "done" 
    Task secondTask = firstTask.ContinueWith(..., TaskContinuationOptions.OnlyOnRanToCompletion); 

    Action<TasK> errorContinuation = x => 
     { 
      taskCompletionSource.SetException(e.Exception); 
     }; 

    firstTask.ContinueWith(errorContinuation, TaskContinuationOptions.OnlyOnFaulted); 
    secondTask.ContinueWith(errorContinuation, TaskContinuationOptions.OnlyOnFaulted); 

    return taskCompletionSource.Task; 
} 

Es importante destacar que:

  • la tarea devuelto por InitializeAsync no se considera completa hasta que el secondTask así lo decide
  • secondTask solo se ejecuta si firstTask es correcto
  • error de firstTask o secondTask hace que la tarea general falle

Lo que me pregunto es si hay una más limpia, más simple manera de expresar esto mientras que el logro de la misma funcionalidad. Estoy usando .NET 4.0 pero estoy interesado en si 4.5 también lo hace más fácil.

+1

en 4.5 usted puede hacer esto con funciones de espera/asincrónicas y probar/atrapar simplemente juntándose las tareas dentro de una función asíncrona – Carsten

+0

Tuve el mismo problema recientemente y seguí la misma ruta hasta que encontré la publicación del blog de Stephen Toub que la respuesta de Gideon se relaciona con. Es mucho más limpio y, obviamente, maneja todos los casos de esquina que mi intento inicial de solución. – shambulator

Respuesta

5

para .NET 4.0, que utiliza una idea de this blog article a las tareas de la cadena como usted describe. En particular, mira la sección titulada Luego. No es que su versión espera que usted pueda pasar en una función que devuelve una tarea en vez de pasar un método igual que lo haría a ContinueWith

Como acotación al margen, Then le consigue bastante cerca de la SelectMany que tendría que ser capaz de cadena las tareas a través de cláusulas LINQ. Menciono esto principalmente como una opción de sintaxis hasta async/await en .NET 4.5, aunque en realidad no lo uso yo.

+0

Esta es una solución limpia y genérica que me sorprende que no esté en el BCL, aunque 'TaskCompletionSource' ciertamente lo hace lo suficientemente simple como para implementarlo. Si desea una firma más parecida a 'ContinueWith', debe proporcionar sobrecargas para especificar tokens de cancelación, planificadores, etc. – shambulator

+1

Este fue el agujero exacto en mi comprensión que requería relleno. Muchas gracias. –

0

Otra opción sería la creación de sus dos tareas como tareas secundarias adjuntas (anidadas dentro de una tarea de los padres que se les devuelva)

La tarea padre no se completará hasta tareas secundarias adjuntas completa. Los errores secundarios se consideran errores de los padres.

http://msdn.microsoft.com/en-us/library/dd997417.aspx

Cuestiones relacionadas