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.