1

I would like to catch all Task's exceptions of a batch of task, but I don't find the best solution. Maybe anyone can help me please?

I have a function with the following declaration:

public async Task CreateBooking(CreateBookingModel createBookingModel)

In this method a throw exception can be do

If I make a foreach like that:

foreach (DateTime day in EachDay(originalStartDate, originalEndDate))
{
    createBookingModel.StartDate = day;
    createBookingModel.EndDate = day;

    try
    {
        CreateBooking(createBookingModel);
    }
    catch (Exception ex)
    {
       raiseToTeams(ex, "Creation error");
    }
}

I don't received any else if the creation throw an exception. I tried to make that:

List<Task> tasks = new List<>();
foreach (DateTime day in EachDay(originalStartDate, originalEndDate))
{
    createBookingModel.StartDate = day;
    createBookingModel.EndDate = day;
    tasks.Add(CreateBooking(createBookingModel));              
}

try
{
    Task.WaitAll(tasks.toArray());
}
catch(AggregateException ex)
{
    ex.InnerExceptions.ForEach(subExp =>
    {
     if (subExp is ExternalBookingException)
     {
       raiseToTeams(subExp, "Creation error");
     }
    });
}

But I have 2 problems, if only one exception occurs no problem I catch it in the aggregation, if more that one I catch nothing even on a Exception and not a simple Aggregate catch. And if each Task added before WaitAll() is finish, the line block infinitly, that I don't want !

Anybody have a solution plz ?

HasaniH
  • 8,232
  • 6
  • 41
  • 59
Adrien Ruffie
  • 195
  • 4
  • 16

1 Answers1

4

Note, that

CreateBooking(createBookingModel);

just starts the Task and returns it. In order to get Task result you should await it:

try
{
    // await - start task and await for its completion
    await CreateBooking(createBookingModel);
}
catch (Exception ex)
{
    raiseToTeams(ex, "Creation error");
}

Same if you have several tasks to complete:

List<Task> tasks = new List<>();

foreach (DateTime day in EachDay(originalStartDate, originalEndDate))
{
    createBookingModel.StartDate = day;
    createBookingModel.EndDate = day;
    tasks.Add(CreateBooking(createBookingModel));              
}

try
{
    // Note WhenAll instead of WaitAll
    // Note await
    await Task.WhenAll(tasks);
}
catch (Exception ex) // <- Note plain exception, not AggregatedException
{
  ...
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • if 5 exception occurs only one is catch sadly in the catch statement and not the 5 – Adrien Ruffie Dec 25 '22 at 19:03
  • @Adrien Ruffie: if we *combine* `5` tasks with `WhenAll` we are going to have either all tasks completed successfuly or an exception is thrown in one of the tasks. You can try using `WhenAny` to check each task completion – Dmitry Bychenko Dec 25 '22 at 19:25
  • Another possibility is to check `Status` of each task within `tasks`: `if (tasks[i].Status == TaskStatus.Faulted) {...}` – Dmitry Bychenko Dec 25 '22 at 19:29