Parallel.ForEachAsync statt Task.WhenAll

Parallel.ForEachAsync statt Task.WhenAll

- Matt

Ein Batch-Job, der hundert Datensätze verarbeitet, jeder mit einem eigenen HTTP-Aufruf. Mit Task.WhenAll schickt man alle hundert Anfragen gleichzeitig los - bei mir hat das eine Weile gedauert, bis klar war, warum der Drittanbieter nach wenigen Sekunden anfing, mit 429 zu antworten: schlicht zu viele offene Verbindungen auf einmal.

Parallel.ForEachAsync (seit .NET 6, in System.Threading.Tasks) arbeitet die Liste ab, hält dabei aber die Zahl gleichzeitiger Durchläufe über ParallelOptions.MaxDegreeOfParallelism in Grenzen:

var options = new ParallelOptions { MaxDegreeOfParallelism = 8 };
await Parallel.ForEachAsync(ids, options, async (id, ct) =>
{
    await client.GetAsync($"/items/{id}", ct);
});

Der Haken: Anders als Task.WhenAll<T> liefert die Methode keine Rückgabewerte, Ergebnisse müssen selbst in eine threadsichere Collection geschrieben werden. Und das CancellationToken im Delegate sollte man auch wirklich weiterreichen, siehe CancellationToken nicht schlucken.

Doku zu Parallel.ForEachAsync