using System.Diagnostics;
using System.Threading.Tasks;
using Console = System.Console;
static (int, int)[] delays = new (int, int)[]
(1, 200), (2, 500), (3, 300), (4, 400), (5, 300)
static Random rnd = new Random(DateTime.Now.Millisecond);
public static void Main()
private static void ParallelForEach()
Console.WriteLine("Parallel.ForEach()");
var watch = Stopwatch.StartNew();
Parallel.ForEach(delays, ((int I, int Pause) args) => DoWork(now, args.I, args.Pause).Wait());
Console.WriteLine($"Works took {watch.ElapsedMilliseconds}ms");
private static void ParallelForAll()
Console.WriteLine("Parallel.ForAll()");
var watch = Stopwatch.StartNew();
delays.AsParallel().ForAll(((int I, int Pause) args) => DoWork(now, args.I, args.Pause).Wait());
Console.WriteLine($"Works took {watch.ElapsedMilliseconds}ms");
private static void TaskWaitAllLinq()
Console.WriteLine("Task.WaitAll() with Linq");
var watch = Stopwatch.StartNew();
Task.WaitAll(delays.Select(((int I, int Pause) args) => DoWork(now, args.I, args.Pause)).ToArray());
Console.WriteLine($"Works took {watch.ElapsedMilliseconds}ms");
private static void TaskWaitAll()
Console.WriteLine("Task.WaitAll()");
var watch = Stopwatch.StartNew();
var tasks = new Task[delays.Length];
foreach ((int I, int Pause) args in delays)
tasks[args.I - 1] = DoWork(now, args.I, args.Pause);
Console.WriteLine($"Works took {watch.ElapsedMilliseconds}ms");
private static async Task DoWork(DateTime startOn, int i, int pause)
var watch = Stopwatch.StartNew();
Console.WriteLine($"Work #{i} starts after {(DateTime.Now - startOn).TotalMilliseconds:F0}ms and waits for {pause}ms");
while (watch.ElapsedMilliseconds < pause)
var diff = pause - watch.ElapsedMilliseconds;
var wait = diff < 50 ? diff : Math.Round((pause - watch.ElapsedMilliseconds) / 2.0);
await Task.Delay((int)wait);
Console.WriteLine($" #{i}: work in progress...");
for (var j = rnd.Next() % 1_000; 0 < j; j--);
Console.WriteLine($"Work #{i} ends after {watch.ElapsedMilliseconds}ms");