All, there are many question on the above topic but I believe this is sufficiently different to warrant a new question. I have the following Task
and a continuation to deal with a variety of task Status
; TaskStatus.RanToCompletion
, TaskStatus.Canceled
and of course the AggregateException
via TaskStatus.Faulted
. The code looks like
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;
}
}
This all works well, but I am concerned whether or not I am doing this right, as there is the possibility of an AggregateException
being thrown from within the continuation - what then?
I do not want to Wait
on my asyncTask
nor the continuation as this will block the return to the UI Thread. To catch any exceptions thrown from within a continuation can't mean I have to do something like this surely
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...
}
});
would this even work? What is best practice here?
As always, thanks for your time.
You can use traditional try/catch within your delegates watching for AggregateException
or you can chain on specific continuations that will only ever run if the antecedent has faulted using the TaskContinuationOptions.OnlyOnFaulted
option. The latter approach allows for very clean task workflows to be defined. For example:
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);
Msdn has a fairly well written "How to" on the subject: here
You will notice they simply use a try/catch(AggregateException
) block, then filter the exception they know how to handle in ae.Handle(lambda)
and make the app stop if there are some left that aren't handleable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With