Ich habe nur wenige asynchrone REST-Services, die nicht voneinander abhängig sind. Während ich auf eine Antwort von Service1 "warte", kann ich Service2, Service3 usw. anrufen.
Zum Beispiel siehe unten Code:
var service1Response = await HttpService1Async();
var service2Response = await HttpService2Async();
// Use service1Response and service2Response
Nun service2Response
ist nicht abhängig vonservice1Response
und sie können unabhängig abgerufen werden. Daher muss ich nicht auf die Antwort des ersten Dienstes warten, um den zweiten Dienst anzurufen.
Ich glaube nicht, dass ich es gebrauchen kann Parallel.ForEach
, da es sich nicht um eine CPU-gebundene Operation handelt.
Kann ich use aufrufen, um diese beiden Operationen gleichzeitig aufzurufen Task.WhenAll
? Ein Problem bei der Verwendung Task.WhenAll
ist, dass keine Ergebnisse zurückgegeben werden. Um das Ergebnis abzurufen, kann ich task.Result
nach dem Aufruf anrufen Task.WhenAll
, da alle Aufgaben bereits erledigt sind und ich uns nur noch eine Antwort holen muss?
Beispielcode:
var task1 = HttpService1Async();
var task2 = HttpService2Async();
await Task.WhenAll(task1, task2)
var result1 = task1.Result;
var result2 = task2.Result;
// Use result1 and result2
Ist dieser Code in Bezug auf die Leistung besser als der erste? Irgendein anderer Ansatz, den ich verwenden kann?
quelle
I do not think I can use Parallel.ForEach here since it is not CPU bound operation
- Ich sehe die Logik dort nicht. Parallelität ist Parallelität.Parallel.ForEach
neue Threads erzeugt werden, währendasync await
alles in einem einzigen Thread ausgeführt wird.await
) zu verwenden, bevor sie fertig ist.WhenAll
ich davon aus,Result
dass alle Aufgaben abgeschlossen sind, bevor .Result aufgerufen wird. Da Task.Result den aufrufenden Thread blockiert, gehe ich davon aus, dass wenn ich ihn nach Abschluss der Tasks aufrufe, er das Ergebnis sofort zurückgibt. Ich möchte das Verständnis bestätigen.Antworten:
Aber es gibt die Ergebnisse zurück. Sie befinden sich alle in einem Array eines gemeinsamen Typs. Daher ist es nicht immer nützlich , die Ergebnisse dahingehend zu verwenden, dass Sie das Element im Array suchen müssen, das
Task
dem gewünschten Ergebnis entspricht, und es möglicherweise in das zugehörige Element umwandeln Tatsächlicher Typ, daher ist dies in diesem Zusammenhang möglicherweise nicht der einfachste / am besten lesbare Ansatz. Wenn Sie jedoch alle Ergebnisse aus jeder Aufgabe haben möchten und der übliche Typ der Typ ist, als den Sie sie behandeln möchten, ist dies großartig .Ja, das könntest du machen. Sie könnten auch
await
sie (await
würde die Ausnahme in einer fehlerhaften Aufgabe auspacken, währendResult
würde eine aggregierte Ausnahme auslösen , aber sonst wäre es das gleiche).Es führt die beiden Operationen zur gleichen Zeit aus und nicht die eine und die andere. Ob dies besser oder schlechter ist, hängt von den zugrunde liegenden Vorgängen ab. Wenn die zugrunde liegenden Vorgänge "eine Datei von der Festplatte lesen" sind, ist es wahrscheinlich langsamer, sie parallel auszuführen, da es nur einen Plattenkopf gibt und er sich zu einem bestimmten Zeitpunkt nur an einem Ort befinden kann. Das Herumspringen zwischen zwei Dateien ist langsamer als das Lesen einer Datei als der anderen. Wenn die Vorgänge dagegen "Netzwerkanfragen ausführen" (wie hier der Fall), sind sie sehr wahrscheinlich schneller (zumindest bis zu einer bestimmten Anzahl gleichzeitiger Anfragen), da Sie auf eine Antwort warten können Von einem anderen Netzwerkcomputer genauso schnell, wenn auch eine andere ausstehende Netzwerkanforderung aktiv ist. Wenn Sie wissen wollen, ob es
Wenn es für Sie nicht wichtig ist, dass Sie alle Ausnahmen kennen, die für alle Vorgänge gelten, die Sie parallel ausführen, und nicht nur für den ersten, können Sie
await
die AufgabenWhenAll
ganz einfach ausführen . Das Einzige,WhenAll
was Sie bekommen, ist,AggregateException
mit jeder einzelnen Ausnahme von jeder fehlerhaften Aufgabe eine zu haben, anstatt zu werfen, wenn Sie die erste fehlerhafte Aufgabe treffen. Es ist so einfach wie:quelle
Hier ist die Erweiterungsmethode, bei der SemaphoreSlim verwendet wird und ein Höchstmaß an Parallelität eingestellt werden kann
Beispielnutzung:
quelle
Sie können entweder verwenden
oder
quelle