Alex Rivera | Logout

Preserve exception when continuing Task<T>

Asked 2010-12-01T18:14:17.897
10

I've got a Task<T>:

Task<A> someTask = ...

This task can result in being successful, faulted or cancelled.

I want to transform the result when the task is successful, and preserve the outcome if not.

This seems to be really difficult when someTask throws an exception.

What I've tried:

Task<B> resultTask = StartMyTask().ContinueWith<B>(
    t => Foo(t.Result),
    TaskContinuationOptions.OnlyOnRanToCompletion);

This results in resultTask being cancelled if someTask faults. I want it to fault.

Task<B> resultTask = StartMyTask().ContinueWith<B>(
    t => Foo(t.Result));

This breaks into the Visual Studio debugger because .Result throws an exception. If I press F5, resultTask faults as expected, but it smells.

Is there any way to let resultTask to have the same outcome as someTask if someTask faults?


Essentially what I'm trying to do is to express something like this with tasks:

int F()
{
    throw new SomeException();
}

string G(int x)
{
    return x.ToString();
}

try
{
    string result = G(F());
}
catch (SomeException e)
{
    ...
}
Edit
Report

1 Answer

0

When you check Task's result you always get AggregateException. If your error handling code can be separated from main code then you could use kind of a AOP approach, PostSharp for an instance:

[ErrorHandling]
public void doWord()
{
    string result = G(F());
}

where ErrorHandling is:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
[MulticastAttributeUsage(
    MulticastTargets.Method,
    Inheritance = MulticastInheritance.Multicast,
    AllowMultiple = false)]
     public sealed class ErrorHandlingAttribute : OnMethodBoundaryAspect
     {
         public override void OnException(MethodExecutionArgs args)
         {
             base.OnException(args);
             Exception ex = args.Exception;
             AggregateException ae;
             if ((ae = ex as AggregateException) !=null)
                 ex = ae.InnerExceptions[0];

             // your error handling logic
         }
     }

I understand this can be seemed as overkill, but it's just an idea.

answered 2010-12-01T23:18:14.193

Your Answer