我得到了一个像增强的Task.WhenAll
. 它需要一堆任务并在全部完成后返回。
public async Task MyWhenAll(Task[] tasks) {
...
await Something();
...
// all tasks are completed
if (someTasksFailed)
throw ??
}
我的问题是如何让方法返回一个看起来像Task.WhenAll
一个或多个任务失败时返回的任务?
如果我收集异常并抛出异常,AggregateException
它将被包装在另一个 AggregateException 中。
编辑:完整示例
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);
}
因为Task.WhenAll
异常AggregateException
有 2 个内部异常。
因为MyWhenAll
例外是AggregateException
一个内部AggregateException
有 2 个内部例外。
编辑:我为什么要这样做
我经常需要调用分页 API:s 并希望限制同时连接的数量。
实际的方法签名是
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)
这意味着我可以像这样进行分页
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();
一切正常,聚合中的聚合只是一个小不便。