Pick the tool by scenario:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | // ====================================================================== // Q: WhenAll, WhenAny, WhenEach, Parallel: which do you pick? // // Pick the tool by scenario: // - 2-3 independent I/O calls: Task.WhenAll. // - Many items, I/O, with a limit on concurrent calls: Parallel.ForEachAsync // (MaxDegreeOfParallelism) or SemaphoreSlim. // - CPU-bound work over a collection: Parallel.ForEach, PLINQ. // - Results in the order they complete: Task.WhenEach (.NET 9). // - The fastest of two, or a timeout: Task.WhenAny, WaitAsync. // - Producer/consumer within the same process: Channel<T>. // - Across pods / services: message broker + idempotent consumer (Q30-Q31). // - Periodic work: BackgroundService + PeriodicTimer. // ====================================================================== // First wins: query two warehouses, keep the fastest, cancel the other using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct); var primary = warehouseA.GetStockAsync(sku, cts.Token); var backup = warehouseB.GetStockAsync(sku, cts.Token); var winner = await Task.WhenAny(primary, backup); await cts.CancelAsync(); // stops the slower call return await winner; // throws if the faster one failed // WhenEach: show results as they arrive await foreach (var done in Task.WhenEach(warehouses.Select(w => w.GetStockAsync(sku, ct)))) progress.Report(await done); // already completed |