Das ist in Ordnung. Alles, was Sie tun, ist die Aufgabe zu lösen, bevor Sie den Parameter übergeben. Es ist genau das gleiche wie var x = warte auf GetDataAsync; var results = MapResults (x); Macht keinen Unterschied, und es kommt normalerweise auf die Codierungsrichtlinien an, die Sie selbst implementieren möchten
Heinrich
1
Lesbarkeit des Codes. Das ist buchstäblich dasselbe wievar result = await GetDataAsync(); var map = MapResults(result)
Zer0
@ Zer0 welches ist lesbar, das mit var Ergebnissen? oder die einzelne Zeile?
Drew Aguirre
@ Heinrich yup, ich stimme dir zu. Ich mache mir nur Sorgen, dass ich auf meinen Code eine schlechte Praxis anwende, um eine einzelne Zeile zu machen.
Drew Aguirre
3
@DrewAguirre: Die letzten beiden sind völlig unterschiedlich und du darfst nicht später . Ich hoffe das war klar. Ersteres wartet asynchron; Letzterer wartet synchron auf einen asynchronen Workflow. Angenommen, der asynchrone Workflow hat in Zukunft die Arbeit am aktuellen Thread geplant . Ein synchrones Warten bedeutet "Schlaf diesen Thread, bis die Arbeit, die dieser Thread in Zukunft erledigen wird, erledigt ist", und das schläft offensichtlich für immer.
Eric Lippert
Antworten:
28
UPDATE: Diese Frage war das Thema meines Blogs im März 2020 . Weitere Informationen zu diesem Thema finden Sie hier. Danke für die interessante Frage!
Ich gehe hier davon aus, dass Sie beabsichtigt haben, dass dies ein Funktionsaufruf als einziges Mitglied der Argumentliste ist.
Wie andere angemerkt haben, gibt es keinen Unterschied zwischen
x = M(awaitFAsync());
und
var f =awaitFAsync();
x = M(f);
Und das ist das gleiche wie
var ftask =FAsync();
x = M(await ftask)
Es spielt also keine Rolle, wie Sie es schreiben, richtig?
Denken Sie darüber nach.
In diesem speziellen Szenario sind alle drei Workflows gleich. Hier besteht jedoch ein potenzieller Unterschied, wenn wir das Szenario nur geringfügig variieren. Erwägen:
x = M(awaitFAsync(),awaitGAsync());
Dies ist das gleiche wie
var f =awaitFAsync();var g =awaitGAsync();
x = M(f, g);
und was wissen wir über diesen Workflow? Die GAsync-Aufgabe wird erst gestartet, wenn die FAsync-Aufgabe abgeschlossen ist! Es sieht jedoch so aus, als ob hier die Möglichkeit besteht, dass zwei Aufgaben gleichzeitig ausgeführt werden, wodurch der aktuelle Thread möglicherweise effizienter genutzt wird! Wahrscheinlich wäre der Workflow besser geschrieben als:
var ftask =FAsync();var gtask =GAsync();
x = M(await ftask,await gtask);
Jetzt beginnen sowohl FAsync- als auch GAsync-Aufgaben, und wir rufen M erst auf, wenn beide beendet sind.
Mein Rat ist, sorgfältig darüber nachzudenken, wo Sie Ihre Erwartungen stellen. Denken Sie daran, dass ein Warten ein Punkt in einem asynchronen Workflow sein soll, an dem der Workflow asynchron angehalten wird, bis eine Voraussetzung für die Fortsetzung erfüllt ist . Wenn Sie das Warten auf eine Aufgabe verzögern können, bis dies tatsächlich eine Voraussetzung ist, können Sie möglicherweise einen Leistungsgewinn erzielen.
Natürlich ist es gut, sich der zugrunde liegenden Multithreading-Unterstützung der Aufgaben bewusst zu sein, auf die Sie warten. Sie können nicht gleichzeitig auf zwei Aufgaben warten, die Daten aus der Datenbank liefern und dieselben SqlConnectionoder DbContextbeispielsweise verwenden.
Sebazzz
1
Beeindruckend! Ich bin beeindruckt. Tut mir leid, dass ich beschäftigt war und nicht auf Ihre Antwort geantwortet habe. Ich habe diese als Antwort markiert. Die Erklärung ist sehr klar. Und ja, ich habe viel gelernt, indem ich nur die wenigen Zeilen gelesen habe, die Sie geschrieben haben. und ich habe deinen blog auch gelesen .. gute arbeit! und weiter so ..
Drew Aguirre
5
Es gibt keinen Laufzeitunterschied zwischen;
var results =MapResults(awaitGetDataAsync())
und
var tmp =awaitGetDataAsync();var results =MapResults(tmp)
Ja, es gibt keinen Unterschied. Was ich denke, gibt es ein technisches Problem dafür? oder ist es sauberer, die Variable "tmp" zu verwenden? Ich sehe keinen Nachteil für die Verwendung der ersten Zeile. Es gibt sogar eine Ausnahme, die für GetDataAsync () ausgelöst wird.
Drew Aguirre
Ist es eine schlechte Praxis, die erste Zeile zu machen?
Drew Aguirre
Ich bevorzuge das zweite Muster, 1) besser lesbar, 2) ich kann den Code massieren, bevor ich zu den Ergebnissen übergehe.
Harris Yer
Bitte beachten Sie, dass OP Variable ( GetDataAsync) und keinen Methodenaufruf verwendet. Abhängig davon, wo dies Task GetDataAsync = CallSomeAsync()initialisiert wird, kann es zu erheblichen Unterschieden kommen, da die Aufgabe zum Zeitpunkt des Aufrufs bereits ausgeführt MapResults(await GetDataAsync)wird. Siehe Erics Antwort für weitere Details.
Alexei Levenkov
Ja, da es nicht genug Kontext gab, nahm ich an, dass es ein Tippfehler war ...
var result = await GetDataAsync(); var map = MapResults(result)
Antworten:
UPDATE: Diese Frage war das Thema meines Blogs im März 2020 . Weitere Informationen zu diesem Thema finden Sie hier. Danke für die interessante Frage!
Ich gehe hier davon aus, dass Sie beabsichtigt haben, dass dies ein Funktionsaufruf als einziges Mitglied der Argumentliste ist.
Wie andere angemerkt haben, gibt es keinen Unterschied zwischen
und
Und das ist das gleiche wie
Es spielt also keine Rolle, wie Sie es schreiben, richtig?
Denken Sie darüber nach.
In diesem speziellen Szenario sind alle drei Workflows gleich. Hier besteht jedoch ein potenzieller Unterschied, wenn wir das Szenario nur geringfügig variieren. Erwägen:
Dies ist das gleiche wie
und was wissen wir über diesen Workflow? Die GAsync-Aufgabe wird erst gestartet, wenn die FAsync-Aufgabe abgeschlossen ist! Es sieht jedoch so aus, als ob hier die Möglichkeit besteht, dass zwei Aufgaben gleichzeitig ausgeführt werden, wodurch der aktuelle Thread möglicherweise effizienter genutzt wird! Wahrscheinlich wäre der Workflow besser geschrieben als:
Jetzt beginnen sowohl FAsync- als auch GAsync-Aufgaben, und wir rufen M erst auf, wenn beide beendet sind.
Mein Rat ist, sorgfältig darüber nachzudenken, wo Sie Ihre Erwartungen stellen. Denken Sie daran, dass ein Warten ein Punkt in einem asynchronen Workflow sein soll, an dem der Workflow asynchron angehalten wird, bis eine Voraussetzung für die Fortsetzung erfüllt ist . Wenn Sie das Warten auf eine Aufgabe verzögern können, bis dies tatsächlich eine Voraussetzung ist, können Sie möglicherweise einen Leistungsgewinn erzielen.
quelle
SqlConnection
oderDbContext
beispielsweise verwenden.Es gibt keinen Laufzeitunterschied zwischen;
und
quelle
GetDataAsync
) und keinen Methodenaufruf verwendet. Abhängig davon, wo diesTask GetDataAsync = CallSomeAsync()
initialisiert wird, kann es zu erheblichen Unterschieden kommen, da die Aufgabe zum Zeitpunkt des Aufrufs bereits ausgeführtMapResults(await GetDataAsync)
wird. Siehe Erics Antwort für weitere Details.