4

I need help with a simple Task.WhenAll C# code. I have upto 50 different tasks being fired at the same time, however, some of these calls could return an error message.

I am trying to write the exception handling code, so that I can process the ones that worked (which it does), but capture the ones that errored, so I can perform additional code against them.

There is AggregateException, but is there a way to see which call/inputs that created that exception?

I'm unable to share the actual code due to strict company policy, but an example is as follows:

List<ListDetails> libs = getListDetails();
var tasks = new Task<List<ItemDetails>>[libs.Count];
for (int i = 0; i < libs.Count; i++)
{
    tasks[i] = getListItems(libs[i].ServerRelativeUrl, libs[i].ListId);
}

try
{
    await Task.WhenAll(tasks);
}
catch(AggregateException aex)
{
    //Capture which Server RelativeUrls and ListIDs that failed.    
}
1
  • 2
    could you please show your code? Especially how you create and invoke those tasks? Commented Oct 8, 2018 at 8:27

3 Answers 3

7

You can query the original tasks after waiting:

// Tasks taken from any source.
Task[] myTasks = ...;

// Logically wait ("await") for all tasks to complete,
// while ignoring possible exceptions (`Task.WhenAny` doesn't throw).
await Task.WhenAny(Task.WhenAll(myTasks));

// All tasks have completed - examine their outcome as you see fit.
foreach (var task in myTasks) {
 if (myTask.Status == RanToCompletion)
     ...
}

Please note that a previous version of this answer was incorrect. The core idea was sound, but the code contained a mistake.

Sign up to request clarification or add additional context in comments.

Comments

5

You should check the InnerExceptions property, or you can use AggregateException.Flatten method as shown in the docs:

try {
     task1.Wait();
  }
  catch (AggregateException ae) {
     foreach (var e in ae.Flatten().InnerExceptions) {
        if (e is CustomException) {
           Console.WriteLine(e.Message);
        }
        else {
           throw;
        }
     }
  }

This will give you all the exceptions that are thrown by the child tasks but unfortunately there is no way to know which task threw a particular exception. You will need to investigate the stack traces.

2 Comments

does task1.Wait() blocks the UI theard.? for my case, the app goes to non-responsive state. Is there an alternative way to get aggregateException without UI being non-responsive.?
@AnkitDhadse Yes, task.Wait() and Task.WaitAll(tasks) are synchronous (blocking), unlike await task and await Task.WhenAll(tasks). And await unwraps aggregate exceptions, returning the first inner exception. But there are ways to run a set of tasks asynchronously and yet still throw an aggregate exception. See this answer or others on that page.
0

You should make a array of async tasks then when you are going to add each task to array you should place a anonymous function with lambda expression in ContinueWith(){}. Here is an example :

var tasks = new List<Task>(); 
tasks.add(t.ContinueWith(o =>
{
    if(o.IsFaulted){
        Console.WriteLine(o.Exception?.InnerException);
        return;
        }

        Console.WriteLine(o.Result);
  }));

 tasks.WhenAll().ContinueWith(o=>{

Console.WriteLine("All Done!")
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.