2012-03-06 3 views
7

J'ai une méthode avec la structure suivante:composition des tâches et la gestion des erreurs avec 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; 
} 

important:

  • la tâche renvoyée par InitializeAsync n'est pas considérée comme complète jusqu'à ce que le secondTask décide
  • secondTask fonctionne seulement si firstTask est réussie
  • échec de l'un ou l'autre firstTask ou secondTask provoque la tâche globale à l'échec

Ce que je me demande est de savoir s'il y a un produit de nettoyage, de façon plus simple d'exprimer, tout en obtenant les mêmes fonctionnalités. J'utilise .NET 4.0, mais je suis intéressé de savoir si 4.5 rend aussi cela plus facile.

+1

en 4.5 vous pouvez le faire avec les fonctions wait/async et essayer/attraper en branchant simplement les tâches ensemble dans une fonction asynchrone – Carsten

+0

J'ai eu le même problème récemment et suis allé sur le même chemin jusqu'à ce que je trouve le blog Toub que la réponse de Gideon est liée. C'est beaucoup plus propre et gère plus évidemment tous les cas d'angle que ma première tentative de solution. – shambulator

Répondre

5

Pour .NET 4.0, j'ai utilisé une idée de this blog article à des tâches de la chaîne comme vous décrivez. En particulier, regardez la section intitulée puis. Non pas que sa version que vous attend de passer dans une fonction qui retourne une tâche au lieu de simplement passer une méthode comme vous le feriez pour ContinueWith

En aparté, Then vous obtient assez proche de la SelectMany vous devez être en mesure de la chaîne les tâches via LINQ à partir des clauses. Je mentionne ceci principalement comme une option de syntaxe jusqu'à async/await dans .NET 4.5, bien que je n'utilise pas cela moi-même.

+0

Il s'agit d'une solution propre et générique qui, je suis surpris, ne se trouve pas dans la BCL, même si 'TaskCompletionSource' le rend assez simple à implémenter. Si vous voulez une signature plus comme 'ContinueWith', vous devrez fournir des surcharges pour spécifier les jetons d'annulation, les planificateurs, etc. – shambulator

+1

C'était le trou exact dans ma compréhension qui a exigé le remplissage. Merci beaucoup. –

0

Une autre option serait de créer vos deux tâches tâches enfants attachées (imbriquées dans une tâche de parent que vous retournez)

La tâche mère ne sera pas complète tant que les tâches de l'enfant attaché complet. Les erreurs enfants sont considérées comme des erreurs parentales.

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