I’d like to execute multiple async tasks sequentially.
foreach (var msg in messages)
{
await smtp.SendAsync(msg);
}
However, if one of the tasks fails, I’d like the rest of them to continue. And throw one exception at the end.
Think of it like .WhenAll() that executes all the tasks and throws an AggregateException at the end, if any of the tasks fails. However, I cannot find any sequential alternative.
I studied the docs and googled and stackoverflowed for a solution, and I found no built-in way to do this. I think the only way is to handle exceptions manually.
Something like this
var exceptions = new List<Exception>();
foreach (var msg in messages)
{
try
{
await smtp.SendAsync(msg).ConfigureAwait(false);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
if (exceptions.Count > 0)
{
throw new AggregateException("SMTP errors", exceptions);
}
Questions:
- Is there a .NET built-in solution I’m missing?
- If not, is this the right way? Maybe chaining multiple
.ContinueWithcalls and returning the resulting task-chain instead is considered best practice? (thus eliding await/async and prevent unnecessary state-machine building) - Am I allowed to use the .NET built-in
AggregateExceptionhere or this is bad practice?
>Solution :
Is there a .NET built-in solution I’m missing?
No. This is an unusual need, so there’s nothing built-in. When doing sequential operations, it’s far more common to want to stop on the first exception.
If not, is this the right way?
Yes. You can use AggregateException if that’s the semantics you want. You should prefer await over ContinueWith.
You may also want to consider a railway programming pattern. There isn’t anything like a Try/Error/Exceptional monad in the BCL but there are several libraries out there to fill that gap