Ich habe den folgenden Code, der korrekt async / await-Paradigma verwendet.
%Vor%Wie schreibe ich das, wenn ich statt foreach () LINQ ForEach () benutzen möchte? Dieser gibt zum Beispiel Kompilierungsfehler.
%Vor%Der einzige Code, den ich ohne Kompilierungsfehler arbeiten konnte, ist dies.
%Vor%Ich mache mir Sorgen, dass diese Methode keine asynchrone Signatur hat, sondern nur der Körper. Ist das das korrekte Äquivalent zu meinem ersten Block?
Nein. Es ist nicht. Diese ForEach
unterstützt nicht async-await
und erfordert, dass Ihr Lambda async void
ist, was für Event-Handler only verwendet werden sollte. Wenn Sie es verwenden, werden alle Ihre async
-Operationen gleichzeitig ausgeführt und warten nicht darauf, dass sie abgeschlossen werden.
Sie können wie gewohnt eine normale foreach
verwenden, aber wenn Sie eine Erweiterungsmethode wünschen, benötigen Sie eine spezielle async
Version.
Sie können selbst eine erstellen, die über die Elemente iteriert, eine Operation async
und await
s it:
Verwendung:
%Vor% Eine andere (und normalerweise effizientere) Implementierung von ForEachAsync
wäre, alle async
-Operationen und nur dann await
alle zusammen zu starten, aber das ist nur möglich, wenn Ihre Aktionen gleichzeitig ausgeführt werden können, was nicht der Fall ist immer der Fall (zB Entity Framework):
Wie in den Kommentaren angemerkt wurde, möchten Sie wahrscheinlich nicht SaveChangesAsync
in einer foreach verwenden, um damit zu beginnen. Es ist wahrscheinlich effizienter, Ihre Änderungen vorzubereiten und sie dann auf einmal zu speichern.
Um in eine Methode zu schreiben, muss Ihre Methode als async markiert werden. Wenn Sie ForEach-Methode schreiben, die Sie schreiben, erwarten Sie in Ihrem Labda-Ausdruck, der in Begriffen verschiedene Methoden insgesamt ist, die Sie von Ihrer Methode aufrufen. Sie müssen diesen lamdba-Ausdruck in eine Methode verschieben und diese Methode als async markieren und auch als @ i3arnon sagen Sie benötigen eine Async-markierte ForEach-Methode, die noch nicht von .Net Framework bereitgestellt wird. Also müssen Sie es selbst schreiben.
Das erste Beispiel mit foreach
wartet nach jeder Schleifeniteration effektiv.
Das letzte Beispiel ruft List<T>.ForEach()
auf, das eine Action<T>
Bedeutung hat, dh Ihr asynchrones Lambda wird in ein void
Delegat kompiliert, im Gegensatz zu standard Task
.
Effektiv ruft die ForEach()
-Methode "Iterationen" einzeln auf, ohne darauf zu warten, dass sie beendet werden. Dies wird auch an Ihre Methode weitergegeben, was bedeutet, dass AddReferenceData()
möglicherweise beendet wird, bevor die Arbeit erledigt ist.
Also nein, es ist kein Äquivalent und verhält sich ganz anders . Wenn man davon ausgeht, dass es sich um einen EF-Kontext handelt, wird es explodieren, da es möglicherweise nicht für mehrere Threads gleichzeitig verwendet wird.
Lesen Sie auch Ссылка , das von Deepu erwähnt wird warum ist es wahrscheinlich besser, bei foreach
zu bleiben.
Vielen Dank für Ihr Feedback. Wenn ich den "save" -Teil außerhalb der Schleife nehme, glaube ich, dass die folgenden zwei Methoden nun äquivalent sind: eine mit foreach()
, eine andere mit .ForEach()
. Wie von Deepu erwähnt, werde ich Eric's Beitrag lesen, warum foreach
vielleicht besser ist.
Tags und Links .net c# linq async-await