Bounded worker pool with Parallel.ForEachAsync
C#
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
static async Task<(int Ok, IReadOnlyCollection<Exception> Errors)> RunPoolAsync<T>(
IEnumerable<T> items, Func<T, Task> work, int workers)
{
int ok = 0;
var errors = new ConcurrentBag<Exception>();
await Parallel.ForEachAsync(items, new ParallelOptions { MaxDegreeOfParallelism = workers },
async (item, _) =>
{
try { await work(item); Interlocked.Increment(ref ok); }
catch (Exception ex) { errors.Add(ex); }
});
return (ok, errors);
}