8

Tutti, ci sono molte domande sull'argomento sopra, ma credo che questo sia sufficientemente diverso da giustificare una nuova domanda. Ho il seguente Task e una continuazione per gestire una varietà di attività Status; TaskStatus.RanToCompletion, TaskStatus.Canceled e, naturalmente, lo via TaskStatus.Faulted. Il codice è simileTPL e gestione delle eccezioni

Task<bool> asyncTask = Task.Factory.StartNew<bool>(() => 
    asyncMethod(uiScheduler, token, someBoolean), token); 

asyncTask.ContinueWith(task => 
{ 
    // Check task status. 
    switch (task.Status) 
    { 
     // Handle any exceptions to prevent UnobservedTaskException.    
     case TaskStatus.RanToCompletion: 
      if (asyncTask.Result) 
      { 
       // Do stuff... 
      } 
      break; 
     case TaskStatus.Faulted: 
      if (task.Exception != null) 
       mainForm.progressRightLabelText = task.Exception.InnerException.Message; 
      else 
       mainForm.progressRightLabelText = "Operation failed!"; 
     default: 
      break; 
    } 
} 

Questo tutto funziona bene, ma sono preoccupato anche se non sto facendo questo diritto, in quanto v'è la possibilità di un AggregateException gettati dentro la continuazione - che cosa allora?

Io non voglio Wait sul mio asyncTask né la continuazione in quanto ciò bloccherà il ritorno al thread UI. Per intercettare eventuali eccezioni generate dall'interno di una continuazione non può significare che devo fare una cosa del genere sicuramente

Task parentTask = Task.Factory.startNew(() => 
    { 
     Task<bool> asyncTask = Task.Factory.StartNew<bool>(() => 
      asyncMethod(uiScheduler, token, someBoolean), token); 

     Task continueTask = asyncTask.ContinueWith(task => 
      { 
       // My continuation stuff... 
      } 

     try 
     { 
      continueTask.Wait(); 
     } 
     catch(AggregateException aggEx) 
     { 
      // Some handling here... 
     } 
    }); 

Sarebbe questo anche il lavoro? Qual è la migliore pratica qui?

Come sempre, grazie per il vostro tempo.

+0

Ho visto attività che "corsero al completamento" quando in realtà hanno lanciato un'eccezione Aggregate. Questo tipo di gestione degli errori non funziona. Perché non usare solo un try/catch? –

+0

Intendi nel metodo chiamato sul thread in background o nel metodo di deleghe di continuazione effettivo? – MoonKnight

risposta

12

È possibile usare tradizionale try/catch all'interno dei vostri delegati guardare per AggregateException oppure è possibile concatenare in continuazioni specifici che sempre e solo eseguito se l'antecedente è in errore utilizzando l'opzione TaskContinuationOptions.OnlyOnFaulted. Quest'ultimo approccio consente di definire flussi di lavoro delle attività molto puliti. Ad esempio:

Task myRootTask = ....; 

myRootTask.ContinueWith(rootAntecdent => 
{ 
    // this will only be executed if the antecedent completed successfully, no need to check for faults 
}, 
TaskContinuationOptions.OnlyOnRanToCompletion); 

myRootTask.ContinueWith(rootAntecedent => 
{ 
    // this will only be executed if the antecedent faulted, observe exception and handle accordingly 
}, 
TaskContinuationOptions.OnlyOnFaulted); 
2

Msdn ha un abbastanza ben scritto "Come" sul tema: here

Si noterà che utilizzano semplicemente a) blocco try/catch(AggregateException, poi filtrare l'eccezione che sanno come gestire in ae.Handle(lambda) e rendere la fermata app se ce ne sono alcuni che non sono maneggiabili.

+0

Sono a conoscenza di esempi come quelli forniti dal tuo link e non hanno alcun problema con la gestione dell'eception _questo modo_. Il mio problema è come gestire le eccezioni generate dalle continuazioni senza racchiudere l'intero delegato di continuazione con un tentativo di cattura, quindi ancora una volta questo potrebbe essere l'unico modo. Voglio conoscere la migliore parodia per codice del mondo reale, non la migliore pratica del codice giocattolo Microsoft. Saluti. – MoonKnight

+0

+1 per il collegamento. Molto utile – SleepyBoBos

+0

L'OP vuole sapere come farlo senza usare Wait. Gli esempi tutti Aspetta il compito. Prova questo link [http://msdn.microsoft.com/en-us/library/dd997415.aspx]. –