Wir haben diese Methode:
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
string urlContents = await getStringTask;
//The thing is that this returns an int to a method that has a return type of Task<int>
return urlContents.Length;
}
Tritt eine implizite Konvertierung zwischen Task<int>
und auf int
? Wenn nicht, was passiert dann? Wie ist es implementiert, um zu funktionieren?
async
Schlüsselwort darum kümmert .Antworten:
Nee. Dies ist nur ein Teil dessen, wie
async
/await
funktioniert.Jede als deklarierte Methode
async
muss den Rückgabetyp haben:void
(wenn möglich vermeiden)Task
(kein Ergebnis über die Benachrichtigung über Fertigstellung / Fehler hinaus)Task<T>
(für ein logisches Ergebnis des TypsT
auf asynchrone Weise)Der Compiler führt alle erforderlichen Umbrüche durch. Der Punkt ist, dass Sie asynchron zurückkehren
urlContents.Length
- Sie können die Methode nicht einfach zurückgeben lassenint
, da die eigentliche Methode zurückkehrt, wenn sie auf den erstenawait
Ausdruck trifft, der noch nicht abgeschlossen ist. Stattdessen wird a zurückgegeben,Task<int>
das abgeschlossen wird, wenn die asynchrone Methode selbst abgeschlossen ist.Beachten Sie, dass
await
das Gegenteil der Fall ist - es packt aTask<T>
in einenT
Wert aus. So funktioniert diese Zeile:... aber natürlich wird es asynchron entpackt, während nur die Verwendung
Result
blockieren würde, bis die Aufgabe abgeschlossen ist. (await
Kann andere Typen auspacken, die das erwartete Muster implementieren, wird aberTask<T>
wahrscheinlich am häufigsten verwendet.)Dieses doppelte Ein- und Auspacken ermöglicht es Async, so zusammensetzbar zu sein. Zum Beispiel könnte ich eine andere asynchrone Methode schreiben, die Ihre aufruft und das Ergebnis verdoppelt:
(Oder einfach
return await AccessTheWebAsync() * 2;
natürlich.)quelle
async
/ zu befassen,await
und finde das äußerst unintuitiv. IMO sollte es ein Schlüsselwort oder ähnliches gebenreturn
, um dies zu verdeutlichen, z. B.return async result;
(auf die gleiche Weise,await result
wie dasT
aus dem "ausgepackt" wirdTast<T>
).await
- mitT foo = someTaskT;
"Sie können den Typ nicht implizit konvertierenTask<T>
inT
" erhalten - auf die gleiche Weise, wie ich behaupte, dass es sinnvoller wäre, ein Schlüsselwort für die Umkehrung zu haben (EinwickelnTask<T>
). Ich bin alle dafür, Flusen zu entfernen, aber in diesem Fall denke ich, dass dies eine unnötige Verschleierung innerhalb derasync
Methoden darstellt. (Offensichtlich ist der Punkt strittig, weil die Kräfte, die bereits gesprochen / codiert wurden!)async
, denke ich, dass das ausreicht.Nein erfordert die Konvertierung der Aufgabe in int. Verwenden Sie einfach das Aufgabenergebnis.
Wenn verfügbar, wird der Wert zurückgegeben, andernfalls wird 0 zurückgegeben.
quelle
Result
; es kann Deadlocks verursachen! Betrachten Sie zum Beispiel diesen Workflow: (1) Schreiben Sie eine Notiz mit der Aufschrift "Rasen mähen". (2) Warten Sie, bis der Rasen gemäht ist. (3) Essen Sie ein Sandwich. (4) Tun Sie, was auf dem Zettel steht. "Mit diesem Workflow essen Sie niemals ein Sandwich oder mähen den Rasen, da Schritt 2 ein synchrones Warten ist über etwas, das Sie in Zukunft tun werden . Aber das ist der Workflow, den Sie hier beschreiben.