2012-03-06 15 views
7

Ho un metodo con la seguente struttura:composizione Task e gestione degli errori 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; 
} 

importanza:

  • il compito restituito da InitializeAsync non è considerata completa fino secondTask decide così
  • secondTask funziona solo se ha esito positivo
  • errore.210 o secondTask fa sì che il compito generale di fallire

Quello che mi chiedo è se c'è un più pulito, più semplice modo per esprimere questo mentre ottenere la stessa funzionalità. Sto usando .NET 4.0, ma mi interessa sapere se 4.5 rende tutto questo più semplice.

+1

in 4.5 si può fare questo con funzioni attendi/asincroni e provare/catturare semplicemente collegando le attività insieme all'interno di una funzione asincrona – Carsten

+0

Ho avuto lo stesso problema di recente e ho proseguito lungo lo stesso percorso fino a quando ho trovato il post sul blog di Stephen Toub a cui la risposta di Gideon si collega. È molto più pulito e più ovviamente gestisce tutti i casi d'angolo rispetto al mio primo tentativo di soluzione. – shambulator

risposta

5

Per .NET 4.0, ho usato un'idea da this blog article a compiti catena come si descrive. In particolare, guarda la sezione Quindi. Non che la sua versione si aspetta di passare in una funzione che restituisce un compito invece di passare un metodo come si farebbe per ContinueWith

Per inciso, Then si ottiene abbastanza vicino alla SelectMany si avrebbe bisogno di essere in grado di catena le attività tramite LINQ dalle clausole. Lo menziono principalmente come opzione di sintassi fino async/await in .NET 4.5, anche se in realtà non lo uso personalmente.

+0

Questa è una soluzione generica e pulita che mi sorprende non sia nel BCL, sebbene 'TaskCompletionSource' lo renda abbastanza semplice da implementare. Se vuoi una firma più come 'ContinueWith', devi fornire sovraccarichi per specificare i token di cancellazione, gli scheduler, ecc. – shambulator

+1

Questo è stato il buco esatto nella mia comprensione che richiedeva il riempimento. Grazie mille. –

0

Un'altra opzione sarebbe quella di creare le due attività come attività figlio allegati (annidati all'interno di un'attività principale che si restituisce)

l'attività principale non sarà completa finché attività figlio attaccato completa. Gli errori secondari sono considerati errori padre.

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