public static async Task ForEach <TElement>(IEnumerable <TElement> elements, Action <TElement> perform, int mdop = -1) { if (mdop == -1) { mdop = Environment.ProcessorCount * 2; } if (mdop < 2) { mdop = 2; } SynchronizingEnumerator <TElement> enumerator = new SynchronizingEnumerator <TElement>(elements.GetEnumerator()); Task[] waiters = new Task[mdop - 1]; HashSet <Exception> exceptions = new HashSet <Exception>(); TElement current; while (enumerator.TryTakeNext(out current)) { TElement localCurrent = current; int slot = await FindFreeSlotAsync(waiters, exceptions); waiters[slot] = Task.Run(() => perform(localCurrent)); } try { await Task.WhenAll(waiters.Where(x => x != null)); } catch (Exception ex) { exceptions.Add(ex); } if (exceptions.Count > 0) { throw new AggregateException(exceptions); } }