2012-03-06 13 views
7

Mam metodę o następującej strukturze:skład Task i obsługi błędów z OC

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; 
} 

ważne:

  • zadanie zwrócony przez InitializeAsync nie uważa się za zakończoną, aż secondTask postanawia więc
  • secondTask działa tylko po pomyślnym wykonaniu firstTask
  • niepowodzeniem albo firstTask lub secondTask powoduje awarię całego zadania

Zastanawiam się, czy istnieje czystszy i prostszy sposób wyrażenia tego przy jednoczesnym osiągnięciu tej samej funkcjonalności. Korzystam z .NET 4.0, ale jestem zainteresowany tym, czy 4.5 też to ułatwia.

+1

w wersji 4.5 możesz to zrobić z funkcjami oczekującymi/asynchronicznymi i próbować/złapać, po prostu podkręcając zadania wewnątrz funkcji async – Carsten

+0

Miałem ten sam problem ostatnio i udałem się w dół tą samą trasą aż znalazłem wpis na blogu autorstwa Stephena Uderz, że odpowiedź Gideona jest połączona. Jest o wiele czystszy i lepiej obsługuje wszystkie przypadki narożne niż moja pierwsza próba rozwiązania. – shambulator

Odpowiedz

5

dla .NET 4.0, kiedyś pomysł z this blog article do zadań łańcucha jak opisujesz. W szczególności spójrz na sekcję zatytułowaną , a następnie. Nie dlatego, że jego wersja oczekuje, aby przejść w funkcję, która zwraca zadanie zamiast po prostu przechodząc sposób jak byś do ContinueWith

Tak na marginesie, Then dostaje całkiem blisko do SelectMany trzeba by móc łańcucha zadania za pośrednictwem LINQ z klauzul. Wspominam o tym głównie jako opcji składni do asynchronizacji/poczekać w .NET 4.5, chociaż sam tego nie używam.

+0

To jest czyste, ogólne rozwiązanie, które mnie zaskoczyło, nie jest w BCL, chociaż 'TaskCompletionSource' z pewnością czyni go wystarczająco prostym do wdrożenia. Jeśli chcesz mieć podpis bardziej przypominający "ContinueWith", musisz podać przeciążenia, aby określić tokeny anulowania, harmonogramy itp. – shambulator

+1

To była dokładna luka w moim rozumieniu, która wymagała wypełnienia. Dziękuję bardzo. –

0

Innym rozwiązaniem byłoby, aby utworzyć dwa zadania dołączonych zadań dzieckiem (zagnieżdżone wewnątrz zadania nadrzędnego którego powrót)

Zadanie rodzica nie będzie kompletny, dopóki załączonych zadań podrzędnych kompletny. Błędy dziecka są uważane za błędy nadrzędne.

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

Powiązane problemy