using System.Threading.Tasks;
using System.Collections.Generic;
await Process(Ints(), 10);
static IEnumerable<int> Ints(){
for(var i = 0; i < 100; i++){
async Task DoThingAsync(int i){
Console.WriteLine($"Starting {i}");
await Task.Delay(20 + i + (i%5 * 100));
Console.WriteLine($"Done {i}");
async Task Process(IEnumerable<int> ints, int maxDegreeOfParallellism){
var currentTasks = new List<Task>();
currentTasks.Add(DoThingAsync(n));
if(currentTasks.Count < maxDegreeOfParallellism){
var completedTask = await Task.WhenAny(currentTasks);
currentTasks.Remove(completedTask);
await Task.WhenAll(currentTasks);