2

Let's say I have an Interface:

interface A { string Do(); } 

and then I implement this interface in a class. The implementation requires some async operations. Something like the following:

class B : A { public string Do() { return Task1().Result; } private async Task<string> Task1() { var str = await Task2(); return str + "task1"; } private async Task<string> Task2() { using (WebClient client = new WebClient()) { return System.Text.Encoding.UTF8.GetString(await client.DownloadDataTaskAsync(new Uri("http://test.com"))); } } } 

What is the proper way to return, to the external calling code, the first exception that occurs in the async operations chain? Is the following a good approach?

public string Do() { try { return Task1().Result; } catch (AggregateException ex) { Exception inner = ex; while(inner.InnerException != null) { inner = inner.InnerException; } throw inner; } } 
0

1 Answer 1

2

From your code, through the while, I think you want to throw the first exception in AggregateException To do that, you can use Flatten

Flattens an AggregateException instances into a single, new instance.

It helps to put the exceptions in "the same hierarchy", you can then simply call FirstOrDefault to get the first exception.

Supposed this code:

Task.Factory.StartNew( async () => { await Task.Factory.StartNew( () => { throw new Exception("inner"); }, TaskCreationOptions.AttachedToParent); throw new Exception("outer"); }).Wait(); } 

The stucture of exceptions likes

AggregateException Exception: outer AggregateException Exception: inner 

With Flatten, I can get inner

catch(AggregateException ex) { Console.WriteLine(ex.Flatten().InnerExceptions.FirstOrDefault().Message); } 

but without Flatten, I get AggregateException, which isn't correct

catch(AggregateException ex) { Console.WriteLine(ex.Flatten().InnerExceptions.FirstOrDefault().Message); } 

With your case, this line can help you get the first exception

ex.Flatten().InnerExceptions.FirstOrDefault().Message 

You have also the method Handle, which help you handle the exception inside AggregateException

catch (AggregateException ex) { ex.Handle(x => { if (x is UnauthorizedAccessException) { //the exception you interested throw x; } // Other exceptions will not be handled here. //some action i.e log return false; }); } 
Sign up to request clarification or add additional context in comments.

2 Comments

But it's a good idea to return the first exception to the caller, right?
For me, I handle the exception that I care, that means I throw it. Others, I skip. Look at the answer update.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.