I3arnon die Antwort mit TPL Dataflow ist gut; Dataflow ist besonders nützlich, wenn Sie über eine Mischung aus CPU- und E/A-gebundenem Code verfügen. Ich stimme seinem Gefühl zu, dass Parallel
für CPU-gebundenen Code entwickelt wurde; es ist nicht die beste Lösung für E/A-basierten Code und insbesondere nicht für asynchronen Code geeignet.
Wenn Sie eine alternative Lösung wollen, die gut mit meist-I/O-Code funktioniert - und benötigt keine externe Bibliothek - die Methode, die Sie suchen ist Task.WhenAll
:
var tasks = uris.Select(uri => SendRequestAsync(uri)).ToArray();
await Task.WhenAll(tasks);
Dies ist einfachste Lösung, aber es hat den Nachteil, alle Anfragen gleichzeitig zu starten. Insbesondere wenn alle Anfragen an denselben Dienst (oder eine kleine Gruppe von Diensten) gehen, kann dies zu Zeitüberschreitungen führen. Um dies zu lösen, müssen Sie eine Art Drosselung verwenden ...
Gibt es eine Funktion (z. B. TPL-Partitionierer), die die Anzahl der maximalen Aufgaben steuert und den maximalen HttpClient, den ich erstellen kann?
TPL Dataflow hat diese nette MaxDegreeOfParallelism
, die nur so viele gleichzeitig startet. Sie können drosseln auch regelmäßige asynchronen Code durch einen anderen builtin verwenden, SemaphoreSlim
:
private readonly SemaphoreSlim _sem = new SemaphoreSlim(50);
private async Task SendRequestAsync(Uri uri)
{
await _sem.WaitAsync();
try
{
...
}
finally
{
_sem.Release();
}
}
Bei Aufgabe anstelle, was ist die beste Praxis große Anzahl von ihnen für das Erstellen? Nehmen wir an, ich benutze Task.Factory.StartNew() und füge diese Aufgaben zu einer Liste hinzu und warte auf alle.
Sie wollen eigentlich nicht StartNew
verwenden. Es gibt nur einen geeigneten Anwendungsfall (dynamic task-based parallelism), der extrem selten ist. Moderner Code sollte Task.Run
verwenden, wenn Sie Arbeit auf einen Hintergrund-Thread schieben müssen. Aber das brauchst du nicht einmal, also ist weder StartNew
noch Task.Run
hier angebracht.
Es gibt einige ähnliche Fragen zu SO, aber niemand erwähnt die Höchstwerte. Die Anforderung besteht lediglich darin, maximale Aufgaben mit maximalem HttpClient zu verwenden.
Höchstwerte sind wo asynchronen Code wirklich knifflig wird. Mit CPU-gebundenem (parallelem) Code ist die Lösung offensichtlich: Sie verwenden so viele Threads, wie Sie Kerne haben. (Nun, zumindest können Sie starten dort und nach Bedarf anpassen). Bei asynchronem Code ist eine Lösung nicht so offensichtlich. Es hängt von vielen Faktoren ab - wie viel Speicher Sie haben, wie der Remote-Server reagiert (Geschwindigkeitsbegrenzung, Timeouts, etc.), etc.
Es gibt keine einfachen Lösungen hier. Sie müssen nur testen, wie Ihre spezifische Anwendung mit einem hohen Grad an Nebenläufigkeit umgeht, und dann auf eine niedrigere Zahl drosseln.
Ich habe einige slides for a talk, dass, wenn verschiedene Technologien geeignet sind, zu erklären versucht (Parallelität, Asynchronität, TPL Datenfluss, und Rx). Wenn Sie eher eine schriftliche Beschreibung mit Rezepten bevorzugen, können Sie von my book auf Nebenläufigkeit profitieren.
Was ist, wenn die Anzahl der gleichzeitigen Anfragen überschreitet die maximale Anzahl von HTTP-Anfrage Betriebssystem machen kann? – ozgur
@ozgur Das hängt davon ab, wo dieses Limit konfiguriert ist. Aber wenn es einen gibt, dann stelle sicher, dass 'MaxDegreeOfParallelism' auf etwas niedriger als das gesetzt ist. – i3arnon
Letzte Frage. Das von Ihnen bereitgestellte Beispiel ist für IO-Operationen geeignet, erfordert jedoch keine CPU-Parallelität? – ozgur