Reputation: 331
I would like to run something like this and wait on it, as a whole:
Task task1 = Task.Factory.StartNew(() => MethodThatCouldThrow());
Task task2 = task1.ContinueWith(t => HandleFailure(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
Note that there are a few discussions on the topic already (links below), but they do not quite answer this:
How can one avoid exception handling for normal cases. The normal cases are:
Why can't I wait just on task2? Because it's "Canceled" if task1 succeeds.
Why can't I wait just on task1? Because it's "Faulted" if it failed (and task2 may still be running).
Why can't I wait on both tasks? Because task2 is "Canceled" if task1 succeeds, and this wait throws.
Couple of possible workarounds (however they do not meet desired conditions):
Relevant threads I could find:
Waiting on a Task with a OnlyOnFaulted Continuation causes an AggregateException
Using Tasks with conditional continuations
Thanks!
Upvotes: 3
Views: 629
Reputation: 171246
You should probably first wait until both tasks are completed. Then examine the tasks using any predicate you like and decide based on that.
You can wait for the two tasks either by simply ignoring any exceptions that the wait throws (which I think is dirty since it is exception-based control flow), or:
var combinedTask = Task.WhenAll(task1, task2);
var combinedTaskNoError = combinedTask.ContinueWith(_ => { }, TCO.ExecuteSynchronously);
await combinedTaskNoError; //Will not throw.
That middle line should probably be encapsulated in a helper method. I'd call it WhenCompleted
.
Upvotes: 2
Reputation: 2289
For your first point using Task.WhenAll(task1,task2).Wait()
should suffice.
As for your second point, you can ignore task 2 being cancelled like so
combinedTask.ContinueWith(_=>{
if (_.IsFaulted){
if (typeof(_.Exception) == typeof(TaskCancelledException){
// Do Nothing
}
}
})
If you know the exception type of task1's failure, you could handle this the same way. Depending on how you chain the tasks together, it could only ever produce AggregateExceptions, which would mean that you would need to be doing you Exception type check on InnnerExceptions until you reach an exception that is not of type AggregateException
Upvotes: 2