I got an async method working like an enhanced Task.WhenAll. It takes a bunch of tasks and returns when all are completed.
public async Task MyWhenAll(Task[] tasks) {
    ...
    await Something();
    ...
    // all tasks are completed
    if (someTasksFailed)
        throw ??
}
My question is how do I get the method to return a Task looking like the one returned from Task.WhenAll when one or more tasks has failed?
If I collect the exceptions and throw an AggregateException it will be wrapped in another AggregateException.
Edit: Full Example
async Task Main() {
    try {
        Task.WhenAll(Throw(1), Throw(2)).Wait();
    }
    catch (Exception ex) {
        ex.Dump();
    }
    try {
        MyWhenAll(Throw(1), Throw(2)).Wait();
    }
    catch (Exception ex) {
        ex.Dump();
    }
}
public async Task MyWhenAll(Task t1, Task t2) {
    await Task.Delay(TimeSpan.FromMilliseconds(100));
    try {
        await Task.WhenAll(t1, t2);
    }
    catch {
        throw new AggregateException(new[] { t1.Exception, t2.Exception });
    }
}
public async Task Throw(int id) {
    await Task.Delay(TimeSpan.FromMilliseconds(100));
    throw new InvalidOperationException("Inner" + id);
}
For Task.WhenAll the exception is AggregateException with 2 inner exceptions.
For MyWhenAll the exception is AggregateException with one inner AggregateException with 2 inner exceptions.
Edit: Why I am doing this
I often need to call paging API:s and want to limit number of simultaneous connections.
The actual method signatures are
public static async Task<TResult[]> AsParallelAsync<TResult>(this IEnumerable<Task<TResult>> source, int maxParallel)
public static async Task<TResult[]> AsParallelUntilAsync<TResult>(this IEnumerable<Task<TResult>> source, int maxParallel, Func<Task<TResult>, bool> predicate)
It means I can do paging like this
var pagedRecords = await Enumerable.Range(1, int.MaxValue)
                                   .Select(x => GetRecordsAsync(pageSize: 1000, pageNumber: x)
                                   .AsParallelUntilAsync(maxParallel: 5, x => x.Result.Count < 1000);
var records = pagedRecords.SelectMany(x => x).ToList();
It all works fine, the aggregate within aggregate is just a minor inconvenience.
 
     
     
    