Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly rethrow an exception of task already in faulted state?

I have a synchronous method which, amongst other things, checks the status of a pending task and rethrows its exception, if any:

void Test(Task task)
{
    // ...
    if (task.IsFaulted)
        throw task.Exception;
    // ...
}

This doesn't propagate the exception stack trace information and is debugger-unfriendly.

Now, if the Test was async, it would not be as simple and natural as this:

async Task Test(Task task)
{
    // ...
    if (task.IsFaulted)
        await task; // rethrow immediately and correctly
    // ...
}

Question: how to do it right for a synchronous method? I have come up with this but I do not like it:

void Test(Task task)
{
    // ...
    if (task.IsFaulted)
        new Action(async () => await task)();
    // ...
}
like image 738
avo Avatar asked Nov 24 '13 02:11

avo


People also ask

When should you Rethrow an exception?

If a catch block cannot handle the particular exception it has caught, you can rethrow the exception. The rethrow expression ( throw without assignment_expression) causes the originally thrown object to be rethrown.

How to handle task exception?

Exceptions are propagated when you use one of the static or instance Task. Wait methods, and you handle them by enclosing the call in a try / catch statement. If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, multiple exceptions could be thrown.

Is it possible to Rethrow an exception True or false?

If a catch block cannot handle the particular exception it has caught, we can rethrow the exception. The rethrow expression causes the originally thrown object to be rethrown.

What happens when a task throws an exception?

When exceptions happen, all the exceptions are re-thrown by the calling thread. To do that they're wrapped inside AggregateException and returned to the caller. So when we await a task, we only get the first exception from a collection of exceptions that might exist on a task.


1 Answers

To properly re-throw an exception, you should use ExceptionDispatchInfo:

ExceptionDispatchInfo.Capture(task.Exception.InnerException).Throw();

You can also do:

task.GetAwaiter().GetResult();

P.S. Your Action approach will not work correctly, since you're creating an async void method, and you cannot catch exceptions propagated from that method.

like image 158
Stephen Cleary Avatar answered Sep 19 '22 13:09

Stephen Cleary