using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
public static async Task Main()
var stopWatch1 = Stopwatch.StartNew();
var results1 = await QueryApiAsParallel();
var stopWatch2 = Stopwatch.StartNew();
var results2 = await QueryApiAsParallelOptimized();
Console.WriteLine($"Query1: {stopWatch1.ElapsedMilliseconds} ms ({results1.Select(s => int.Parse(s)).Sum()})");
Console.WriteLine(string.Join(',', results1));
Console.WriteLine($"Query2: {stopWatch2.ElapsedMilliseconds} ms ({results2.Select(s => int.Parse(s)).Sum()})");
Console.WriteLine(string.Join(',', results2));
public static async Task<string[]> QueryApiAsParallelOptimized() {
var results = new ConcurrentBag<string[]>();
var partitions = Enumerable.Range(0, maximum);
var chunks = partitions.Chunk(rangeSize);
var parallelOptions = new ParallelOptions()
MaxDegreeOfParallelism = 1000
await Parallel.ForEachAsync(chunks, parallelOptions, async (range, token) =>
int skip = range.First();
string[] names = await CallApiAsync(skip, rangeSize);
string[] flattened = results.SelectMany(x => x).ToArray();
public static async Task<string[]> QueryApiAsParallel() {
Task<string[]>[] tasks = Partitioner.Create(0, maximum, rangeSize).AsParallel().Select(async (range, index) =>
string[] names = await CallApiAsync(skip, rangeSize);
string[][] tasksCompleted = await Task.WhenAll(tasks);
string[] flattened = tasksCompleted.SelectMany(x => x).ToArray();
private static async Task<string[]> CallApiAsync(int skip, int take)
return _list.Skip(skip).Take(take).ToArray();
private static List<string> _list = new List<string>();
private static Random _rnd = new Random();
private static void FillList(){
for(var i = 0; i< 100000; i++){
_list.Add($"{_rnd.Next(100,200)}");