Für schnellstes Lernen ..
Verstehen Sie den Ablauf der Methodenausführung (mit einem Diagramm): 3 Minuten
Frage Selbstbeobachtung (Lernsache): 1 min
Schnell durch Syntax Zucker: 5 Minuten
Teilen Sie die Verwirrung eines Entwicklers: 5 Minuten
Problem: Ändern Sie schnell eine reale Implementierung von normalem Code in Async-Code: 2 Minuten
Wohin als nächstes?
Verstehen Sie den Ablauf der Methodenausführung (mit einem Diagramm): 3 Minuten
Konzentrieren Sie sich in diesem Bild nur auf # 6 (nichts weiter)
Bei Schritt 6: Die Ausführung wurde hier gestoppt, da die Arbeit ausgegangen ist. Um fortzufahren, benötigt es ein Ergebnis von getStringTask (eine Art Funktion). Daher verwendet es einen await
Operator, um seinen Fortschritt auszusetzen und dem Aufrufer die Kontrolle (Ausbeute) zurückzugeben (dieser Methode, in der wir uns befinden). Der eigentliche Aufruf von getStringTask erfolgte früher in # 2. Bei # 2 wurde versprochen, ein String-Ergebnis zurückzugeben. Aber wann wird das Ergebnis zurückgegeben? Sollten wir (# 1: AccessTheWebAsync) erneut einen zweiten Anruf tätigen? Wer bekommt das Ergebnis, # 2 (aufrufende Anweisung) oder # 6 (wartende Anweisung)
Der externe Aufrufer von AccessTheWebAsync () wartet jetzt ebenfalls. Der Anrufer wartet also auf AccessTheWebAsync, und AccessTheWebAsync wartet im Moment auf GetStringAsync. Interessant ist, dass AccessTheWebAsync vor dem Warten einige Arbeiten ausgeführt hat (# 4), um möglicherweise Zeit vor dem Warten zu sparen. Die gleiche Freiheit für Multitasking steht auch dem externen Anrufer (und allen Anrufern in der Kette) zur Verfügung, und dies ist das größte Plus dieses asynchronen Dings! Sie haben das Gefühl, es ist synchron oder normal, aber es ist nicht so.
Denken Sie daran, dass die Methode bereits zurückgegeben wurde (# 2) und nicht erneut zurückgegeben werden kann (kein zweites Mal). Woher weiß der Anrufer das? Alles dreht sich um Aufgaben! Aufgabe wurde übergeben. Auf die Aufgabe wurde gewartet (keine Methode, kein Wert). Der Wert wird in Aufgabe festgelegt. Der Aufgabenstatus wird auf Abschluss gesetzt. Der Anrufer überwacht nur die Aufgabe (Nr. 6). 6 # ist also die Antwort darauf, wo / wer das Ergebnis erhält. Lesen Sie weiter für später hier .
Frage Selbstbeobachtung um des Lernens willen: 1 min
Lassen Sie uns die Frage etwas anpassen:
Wie und wann und ? async
await
Tasks
Weil das Lernen Task
automatisch die beiden anderen abdeckt (und Ihre Frage beantwortet)
Schnell durch Syntax Zucker: 5 Minuten
Vor der Konvertierung (ursprüngliche Methode)
internal static int Method(int arg0, int arg1)
{
int result = arg0 + arg1;
IO(); // Do some long running IO.
return result;
}
eine Task-ified-Methode zum Aufrufen der obigen Methode
internal static Task<int> MethodTask(int arg0, int arg1)
{
Task<int> task = new Task<int>(() => Method(arg0, arg1));
task.Start(); // Hot task (started task) should always be returned.
return task;
}
Haben wir Erwarten oder Asynchronisieren erwähnt? Rufen Sie die obige Methode auf und Sie erhalten eine Aufgabe, die Sie überwachen können. Sie wissen bereits, was die Aufgabe zurückgibt. Eine Ganzzahl.
Das Aufrufen einer Aufgabe ist etwas schwierig, und dann werden die Schlüsselwörter angezeigt. Rufen wir MethodTask () auf
internal static async Task<int> MethodAsync(int arg0, int arg1)
{
int result = await HelperMethods.MethodTask(arg0, arg1);
return result;
}
Gleicher Code oben hinzugefügt wie Bild unten:
- Wir warten darauf, dass die Aufgabe erledigt wird. Daher die
await
- Da wir await verwenden, müssen wir verwenden
async
(obligatorische Syntax)
- MethodAsync mit
Async
als Präfix (Codierungsstandard)
await
ist leicht zu verstehen, aber die restlichen zwei ( async
, Async
) können nicht sein :). Nun, es sollte für den Compiler jedoch viel sinnvoller sein. Weitere Informationen für später hier
Es gibt also 2 Teile.
- 'Aufgabe' erstellen
- Erstellen Sie syntaktischen Zucker, um die Aufgabe aufzurufen (
await+async
)
Denken Sie daran, wir hatten einen externen Anrufer für AccessTheWebAsync (), und dieser Anrufer wird auch nicht verschont ... dh er benötigt auch denselben await+async
. Und die Kette geht weiter. Aber es wird immer ein Task
Ende geben.
Alles in Ordnung, aber ein Entwickler war überrascht, dass # 1 (Aufgabe) fehlte ...
Teilen Sie die Verwirrung eines Entwicklers: 5 Minuten
Ein Entwickler hat den Fehler gemacht, nicht zu implementieren, Task
aber es funktioniert immer noch! Versuchen Sie, die Frage und nur die akzeptierte Antwort zu verstehen , hier zur Verfügung gestellt . Ich hoffe, Sie haben gelesen und vollständig verstanden. Die Zusammenfassung ist, dass wir 'Task' möglicherweise nicht sehen / implementieren, es aber irgendwo in einer übergeordneten Klasse implementiert ist. Ebenso ist es in unserem Beispiel MethodAsync()
viel einfacher , eine bereits erstellte Methode aufzurufen, als diese Methode mit a Task
( MethodTask()
) uns selbst zu implementieren. Den meisten Entwicklern fällt es schwer, sich Tasks
beim Konvertieren eines Codes in einen asynchronen Code zurechtzufinden.
Tipp: Versuchen Sie, eine vorhandene Async-Implementierung (wie MethodAsync
oder ToListAsync
) zu finden, um die Schwierigkeit auszulagern. Wir müssen uns also nur mit Async befassen und warten (was einfach und dem normalen Code ziemlich ähnlich ist).
Problem: Ändern Sie schnell eine reale Implementierung von normalem Code in Async-Betrieb: 2 Minuten
Die unten in der Datenschicht gezeigte Codezeile begann zu brechen (an vielen Stellen). Weil wir einen Teil unseres Codes von .Net Framework 4.2. * Auf .Net Core aktualisiert haben. Wir mussten dies in 1 Stunde während der gesamten Anwendung beheben!
var myContract = query.Where(c => c.ContractID == _contractID).First();
kinderleicht!
- Wir haben das EntityFramework-Nuget-Paket installiert, da es QueryableExtensions enthält. Mit anderen Worten, es führt die Async-Implementierung (Aufgabe) durch, sodass wir mit einfachem
Async
und await
in Code überlebendem Material überleben können .
- Namespace = Microsoft.EntityFrameworkCore
Die aufrufende Codezeile wurde wie folgt geändert
var myContract = await query.Where(c => c.ContractID == _contractID).FirstAsync();
Methodensignatur geändert von
Contract GetContract(int contractnumber)
zu
async Task<Contract> GetContractAsync(int contractnumber)
Die aufrufende Methode war ebenfalls betroffen: GetContractAsync(123456);
wurde als aufgerufenGetContractAsync(123456).Result;
Wir haben es überall in 30 Minuten geändert!
Der Architekt sagte uns jedoch, wir sollten die EntityFramework-Bibliothek nicht nur dafür verwenden! Hoppla! Theater! Dann haben wir eine benutzerdefinierte Task-Implementierung (yuk) erstellt. Was du weißt wie. Immer noch einfach! ..noch yuk ..
Wohin als nächstes?
Es gibt ein wunderbares kurzes Video über das Konvertieren synchroner Anrufe in asynchrone Anrufe in ASP.Net Core . Vielleicht ist dies wahrscheinlich die Richtung, in die man nach dem Lesen gehen würde.