Von meinem Verständnis eines der wichtigsten Dinge , die async
undawait
tun , ist Code einfach zu schreiben zu machen und lesen - aber mit ihnen zu Laichen Hintergrund - Threads gleich Logik langen Dauer durchzuführen?
Ich probiere gerade das grundlegendste Beispiel aus. Ich habe einige Kommentare inline hinzugefügt. Kannst du es mir erklären?
// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
Task<int> access = DoSomethingAsync();
// task independent stuff here
// this line is reached after the 5 seconds sleep from
// DoSomethingAsync() method. Shouldn't it be reached immediately?
int a = 1;
// from my understanding the waiting should be done here.
int x = await access;
}
async Task<int> DoSomethingAsync()
{
// is this executed on a background thread?
System.Threading.Thread.Sleep(5000);
return 1;
}
c#
.net
asynchronous
async-await
Dan Dinu
quelle
quelle
Antworten:
Bei Verwendung
async
undawait
generiert der Compiler eine Zustandsmaschine im Hintergrund.Hier ist ein Beispiel, an dem ich hoffentlich einige der wichtigsten Details erläutern kann:
OK, was passiert hier?
Task<int> longRunningTask = LongRunningOperationAsync();
beginnt mit der AusführungLongRunningOperation
Nehmen wir an, dass der Haupt-Thread (Thread-ID = 1)
await longRunningTask
erreicht ist.Wenn der
longRunningTask
nicht fertig ist und noch ausgeführtMyMethodAsync()
wird, kehrt er zu seiner aufrufenden Methode zurück, sodass der Hauptthread nicht blockiert wird. WennlongRunningTask
dies erledigt ist, kehrt ein Thread aus dem ThreadPool (kann ein beliebiger Thread sein)MyMethodAsync()
in seinen vorherigen Kontext zurück und setzt die Ausführung fort (in diesem Fall wird das Ergebnis auf der Konsole gedruckt).Ein zweiter Fall wäre, dass der
longRunningTask
die Ausführung bereits beendet hat und das Ergebnis verfügbar ist. Wennawait longRunningTask
wir das erreichen, haben wir bereits das Ergebnis, sodass der Code weiterhin auf demselben Thread ausgeführt wird. (In diesem Fall wird das Ergebnis auf die Konsole gedruckt.) Dies ist natürlich nicht der Fall für das obige Beispiel, bei dem es sich um einen handeltTask.Delay(1000)
.quelle
Sie sollen asynchronen Code einfach zu schreiben und zu lesen machen, ja.
Ganz und gar nicht.
Das
async
Schlüsselwort aktiviert dasawait
Schlüsselwort. Daher muss jede verwendete Methodeawait
markiert werdenasync
.Nein, da
async
Methoden standardmäßig nicht auf einem anderen Thread ausgeführt werden.Nein.
Sie können mein
async
/await
Intro hilfreich finden. Die offiziellen MSDN-Dokumente sind ebenfalls ungewöhnlich gut (insbesondere der TAP- Bereich), und dasasync
Team hat eine hervorragende FAQ veröffentlicht .quelle
async
Methoden standardmäßig nicht auf einem anderen Thread ausgeführt werden. In Ihrem Beispiel blockiert derSleep()
Aufruf innerhalbDoSomethingAsync()
den aktuellen Thread, wodurch verhindert wird, dass die Ausführung innerhalbbutton1_Click()
bis zumDoSomethingAsync()
Abschluss fortgesetzt wird . Beachten Sie, dass, währendThread.Sleep()
der ausführende Thread blockiert,Task.Delay() does not.
Erläuterung
Hier ist ein kurzes Beispiel für
async
/await
auf hohem Niveau. Darüber hinaus sind noch viele weitere Details zu berücksichtigen.Hinweis:
Task.Delay(1000)
Simuliert die Arbeit für 1 Sekunde. Ich denke, es ist am besten, sich das als Warten auf eine Antwort von einer externen Ressource vorzustellen. Da unser Code auf eine Antwort wartet, kann das System die laufende Aufgabe zur Seite stellen und nach Abschluss darauf zurückgreifen. In der Zwischenzeit kann es andere Arbeiten an diesem Thread ausführen.Im folgenden Beispiel macht der erste Block genau das. Es startet alle Aufgaben sofort (die
Task.Delay
Linien) und setzt sie zur Seite. Der Code wird in derawait a
Zeile angehalten , bis die Verzögerung von 1 Sekunde erreicht ist, bevor zur nächsten Zeile gewechselt wird. Dab
,c
,d
, unde
alle Ausführung fast zur gleichen Zeit wie der Autora
(wegen des Mangels an der await), sollten sie in etwa zur gleichen Zeit in diesem Fall beenden.Im folgenden Beispiel startet der zweite Block eine Aufgabe und wartet darauf, dass sie beendet wird (genau das
await
tut er), bevor die nachfolgenden Aufgaben gestartet werden. Jede Iteration dauert 1 Sekunde. Dasawait
Programm wird angehalten und auf das Ergebnis gewartet, bevor fortgefahren wird. Dies ist der Hauptunterschied zwischen dem ersten und dem zweiten Block.Beispiel
AUSGABE:
Zusätzliche Informationen zu SynchronizationContext
Hinweis: Hier wird es für mich etwas neblig. Wenn ich also in irgendetwas falsch liege, korrigieren Sie mich bitte und ich werde die Antwort aktualisieren. Es ist wichtig, ein grundlegendes Verständnis dafür zu haben, wie dies funktioniert, aber Sie können auskommen, ohne ein Experte dafür zu sein, solange Sie es nie verwenden
ConfigureAwait(false)
, obwohl Sie wahrscheinlich eine Möglichkeit zur Optimierung verpassen werden, nehme ich an.Es ist ein Aspekt dieser , die das macht
async
/await
Konzept etwas schwieriger zu erreichen. Das ist die Tatsache, dass in diesem Beispiel alles auf demselben Thread geschieht (oder zumindest, was in Bezug auf seinen Thread derselbe zu sein scheintSynchronizationContext
). Standardmäßigawait
wird der Synchronisierungskontext des ursprünglichen Threads wiederhergestellt, auf dem er ausgeführt wurde. In ASP.NET haben Sie beispielsweise einen,HttpContext
der an einen Thread gebunden ist, wenn eine Anforderung eingeht. Dieser Kontext enthält Dinge, die für die ursprüngliche HTTP-Anforderung spezifisch sind, z. B. das ursprüngliche Anforderungsobjekt, das beispielsweise Sprache, IP-Adresse, Header usw. Enthält Wenn Sie den Thread nach der Hälfte der Verarbeitung wechseln, versuchen Sie möglicherweise, Informationen aus diesem Objekt auf einem anderen Objekt abzurufenHttpContext
das könnte katastrophal sein. Wenn Sie wissen, dass Sie den Kontext für nichts verwenden, können Sie sich dafür entscheiden, dass Sie sich nicht darum kümmern. Auf diese Weise kann Ihr Code in einem separaten Thread ausgeführt werden, ohne den Kontext mit sich zu bringen.Wie erreichen Sie das? Standardmäßig geht der
await a;
Code davon aus, dass Sie den Kontext erfassen und wiederherstellen möchten:Wenn Sie zulassen möchten, dass der Hauptcode in einem neuen Thread ohne den ursprünglichen Kontext fortgesetzt wird, verwenden Sie einfach false anstelle von true, damit der Kontext nicht wiederhergestellt werden muss.
Nachdem das Programm angehalten wurde, wird es möglicherweise in einem völlig anderen Thread mit einem anderen Kontext fortgesetzt . Hierher würde die Leistungsverbesserung kommen - sie könnte auf jedem verfügbaren Thread fortgesetzt werden, ohne dass der ursprüngliche Kontext wiederhergestellt werden muss, mit dem sie begonnen hat.
Ist das Zeug verwirrend? Hölle ja! Kannst du es herausfinden? Wahrscheinlich! Wenn Sie die Konzepte verstanden haben, fahren Sie mit Stephen Clearys Erklärungen fort, die sich eher an jemanden richten, der ein technisches Verständnis von
async
/await
bereits hat.quelle
await MethodCall()
ist eine absolute Verschwendung? Sie können dasawait
/ genauso gut fallen lassenasync
?await
, wird der Thread meiner Meinung nach wieder in den Pool freigegeben, anstatt ihn zu halten. Dies macht es für andere Zwecke verfügbar, bis die Aufgabe zurückgegeben wirdSchauen Sie sich neben den anderen Antworten auch das Warten an (C # -Referenz).
und genauer gesagt im beigefügten Beispiel wird Ihre Situation ein wenig erklärt
quelle
Task.Delay
Feuern verwendete Timer ausgelöst wird .Zeigen Sie die obigen Erklärungen in Aktion in einem einfachen Konsolenprogramm:
Und die Ausgabe ist:
Somit,
TestAsyncAwaitMethods
. Das kehrt sofort zurück, ohne den aktuellen Thread anzuhalten, und es wird sofort die Meldung "Zum Beenden eine beliebige Taste drücken" angezeigtLongRunningMethod
läuft das im Hintergrund. Sobald dies abgeschlossen ist, greift ein anderer Thread aus Threadpool diesen Kontext auf und zeigt die endgültige Nachricht anSomit wird kein Thread blockiert.
quelle
return 1
Teil verdient eine weitere Erklärung: Mit demawait
Schlüsselwort können Sie den zugrunde liegenden Typ vonTask<T>
direkt zurückgeben, wodurch es einfacher wird, Ihren vorhandenen Code an die Welt des Wartens / Asynchronisierens anzupassen . Sie müssen jedoch keinen Wert zurückgeben, da es möglich ist, a zurückzugeben,Task
ohne einen Rückgabetyp anzugeben, der einer synchronenvoid
Methode entspricht. Beachten Sie, dass C #async void
Methoden zulässt , aber Sie sollten dies vermeiden, es sei denn, Sie befassen sich mit Ereignishandlern.Ich denke, Sie haben mit ein schlechtes Beispiel gewählt
System.Threading.Thread.Sleep
Der Zweck einer
async
Aufgabe besteht darin, sie im Hintergrund ausführen zu lassen, ohne den Hauptthread zu sperren, zDownloadFileAsync
System.Threading.Thread.Sleep
ist nichts, was "getan" wird, es schläft nur und daher ist Ihre nächste Zeile nach 5 Sekunden erreicht ...Lesen Sie diesen Artikel, ich denke, es ist eine großartige Erklärung
async
und einawait
Konzept: http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspxquelle
Thread.Sleep
blockiert den Thread (der Thread kann nichts anderes tun, als im Leerlauf zu sitzen), eine asynchrone Methode jedoch nicht. Im Fall vonDownloadFileAsync
kann der Thread etwas anderes tun, bis eine Antwort vom Remote-Server kommt. Ein besserer Platzhalter für "eine Aufgabe, die Zeit braucht" in einerTask.Delay
asynchronen Methode ist , da dies tatsächlich asynchron ist.async
Schlüsselwort benutzte . Aber seine Methode lief immer noch synchron, und diese Antwort erklärte perfekt, warum: weil er eigentlich keinen asynchronen Code ausführte. Die markierten Methoden werdenasync
immer noch synchron ausgeführt, bis Sieawait
unvollständig sindTask
. Wenn dies nichtawait
der Fall ist , wird die Methode synchron ausgeführt, und der Compiler warnt Sie davor.Hier ist ein schnelles Konsolenprogramm, um es den folgenden Personen klar zu machen. Die
TaskToDo
Methode ist Ihre lang laufende Methode, die Sie asynchronisieren möchten. Die asynchrone Ausführung erfolgt über dieTestAsync
Methode. Die Testschleifenmethode führt dieTaskToDo
Aufgaben nur durch und führt sie asynchron aus. Sie können dies in den Ergebnissen sehen, da sie nicht von Lauf zu Lauf in derselben Reihenfolge abgeschlossen werden. Sie werden nach Abschluss an den Konsolen-UI-Thread gemeldet. Einfach, aber ich denke, die simplen Beispiele bringen den Kern des Musters besser zur Geltung als die komplexeren Beispiele:quelle
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:
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:
await
async
(obligatorische Syntax)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 hierTeilen 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 BeispielMethodAsync()
viel einfacher , eine bereits erstellte Methode aufzurufen, als diese Methode mit aTask
(MethodTask()
) uns selbst zu implementieren. Den meisten Entwicklern fällt es schwer, sichTasks
beim Konvertieren eines Codes in einen asynchronen Code zurechtzufinden.Tipp: Versuchen Sie, eine vorhandene Async-Implementierung (wie
MethodAsync
oderToListAsync
) 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!
kinderleicht!
Async
undawait
in Code überlebendem Material überleben können .Die aufrufende Codezeile wurde wie folgt geändert
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.
quelle
Alle Antworten hier verwenden
Task.Delay()
oder eine andere eingebauteasync
Funktion. Aber hier ist mein Beispiel, das keine dieserasync
Funktionen verwendet:quelle
task.Wait();
und wie es verwendet werden kann, um Async / Warten auf die Hölle zu vermeiden: PDiese Antwort soll einige spezifische Informationen zu ASP.NET enthalten.
Durch die Verwendung von async / await im MVC-Controller ist es möglich, die Thread-Pool-Auslastung zu erhöhen und einen viel besseren Durchsatz zu erzielen, wie im folgenden Artikel erläutert.
http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4
quelle
Async & Await Einfache Erklärung
Einfache Analogie
Eine Person kann auf ihren Morgenzug warten . Dies ist alles, was sie tun, da dies ihre Hauptaufgabe ist, die sie derzeit ausführen. (Synchrone Programmierung (was Sie normalerweise tun!))
Eine andere Person wartet möglicherweise auf ihren Morgenzug, während sie eine Zigarette raucht und dann ihren Kaffee trinkt. (Asynchrone Programmierung)
Was ist asynchrone Programmierung?
Bei der asynchronen Programmierung wählt ein Programmierer einen Teil seines Codes in einem vom Hauptthread der Ausführung getrennten Thread aus und benachrichtigt den Hauptthread nach dessen Abschluss.
Was macht das asynchrone Schlüsselwort eigentlich?
Stellen Sie das asynchrone Schlüsselwort einem Methodennamen wie vor
Ermöglicht dem Programmierer, das Schlüsselwort await beim Aufrufen asynchroner Aufgaben zu verwenden. Das ist alles was es tut.
Warum ist das wichtig?
In vielen Softwaresystemen ist der Hauptthread für Operationen reserviert, die sich speziell auf die Benutzeroberfläche beziehen. Wenn ich einen sehr komplexen rekursiven Algorithmus ausführe, dessen Fertigstellung auf meinem Computer 5 Sekunden dauert, diesen jedoch im Hauptthread (UI-Thread) ausführt. Wenn der Benutzer versucht, auf etwas in meiner Anwendung zu klicken, wird er eingefroren angezeigt da mein Haupt-Thread in die Warteschlange gestellt wurde und derzeit viel zu viele Operationen verarbeitet. Infolgedessen kann der Hauptthread den Mausklick nicht verarbeiten, um die Methode über den Schaltflächenklick auszuführen.
Wann verwenden Sie Async und Await?
Verwenden Sie die asynchronen Schlüsselwörter idealerweise, wenn Sie etwas tun, das nicht die Benutzeroberfläche betrifft.
Nehmen wir also an, Sie schreiben ein Programm, mit dem der Benutzer auf seinem Mobiltelefon skizzieren kann, das jedoch alle 5 Sekunden das Wetter im Internet überprüft.
Wir sollten auf den Anruf warten, den die Abrufanrufe alle 5 Sekunden an das Netzwerk senden, um das Wetter zu ermitteln, da der Benutzer der Anwendung weiterhin mit dem mobilen Touchscreen interagieren muss, um hübsche Bilder zu zeichnen.
Wie verwenden Sie Async und Await?
Im Anschluss an das obige Beispiel finden Sie hier einen Pseudocode zum Schreiben:
Zusätzliche Hinweise - Update
Ich habe vergessen, in meinen ursprünglichen Notizen zu erwähnen, dass Sie in C # nur Methoden abwarten können, die in Aufgaben eingeschlossen sind. Zum Beispiel können Sie diese Methode abwarten:
Sie können nicht auf Methoden warten, die keine Aufgaben wie diese sind:
Fühlen Sie sich frei , den Quellcode für die Task - Klasse zu überprüfen hier .
quelle
Async / Warten
Tatsächlich sind Async / Await ein Schlüsselwortpaar, das nur syntaktischer Zucker zum Erstellen eines Rückrufs einer asynchronen Aufgabe ist.
Nehmen Sie diese Operation als Beispiel:
Der obige Code hat mehrere Nachteile. Fehler werden nicht weitergegeben und sind schwer zu lesen. Aber Async und Await kommen herein, um uns zu helfen:
Warte-Aufrufe müssen in Async-Methoden erfolgen. Dies hat einige Vorteile:
HINWEIS : Async und Await werden verwendet , mit asynchronen Aufrufen nicht diese zu machen. Sie müssen hierfür Task Libary verwenden, z. B. Task.Run ().
Hier ist ein Vergleich zwischen erwarteten und keinen erwarteten Lösungen
Dies ist die nicht asynchrone Lösung:
Dies ist die asynchrone Methode:
Sie können eine asynchrone Methode ohne das Schlüsselwort await aufrufen. Dies bedeutet jedoch, dass alle hier aufgeführten Ausnahmen im Freigabemodus verschluckt werden:
Async und Await sind nicht für paralleles Rechnen gedacht. Sie werden verwendet, um Ihren Haupt-Thread nicht zu blockieren. Wenn es um asp.net- oder Windows-Anwendungen geht, ist es eine schlechte Sache, den Hauptthread aufgrund eines Netzwerkaufrufs zu blockieren. Wenn Sie dies tun, reagiert Ihre App nicht mehr oder stürzt sogar ab.
Weitere Beispiele finden Sie in den ms-Dokumenten .
quelle
Um ehrlich zu sein, denke ich immer noch, dass die beste Erklärung die Zukunft und die Versprechen auf Wikipedia ist: http://en.wikipedia.org/wiki/Futures_and_promises
Die Grundidee ist, dass Sie einen separaten Pool von Threads haben, die Aufgaben asynchron ausführen. Bei der Verwendung. Das Objekt verspricht jedoch, dass es die Operation irgendwann ausführen wird, und gibt Ihnen das Ergebnis, wenn Sie es anfordern. Dies bedeutet, dass es blockiert wird, wenn Sie das Ergebnis anfordern und noch nicht fertig sind, aber ansonsten im Thread-Pool ausgeführt wird.
Von dort aus können Sie Dinge optimieren: Einige Vorgänge können asynchron implementiert werden, und Sie können Dinge wie Datei-E / A und Netzwerkkommunikation optimieren, indem Sie nachfolgende Anforderungen zusammenfassen und / oder neu anordnen. Ich bin mir nicht sicher, ob dies bereits im Task-Framework von Microsoft enthalten ist - aber wenn dies nicht der Fall ist, wäre dies eines der ersten Dinge, die ich hinzufügen würde.
Sie können das zukünftige Muster tatsächlich mit Erträgen in C # 4.0 implementieren. Wenn Sie wissen möchten, wie es genau funktioniert, kann ich diesen Link empfehlen, der gute Arbeit leistet: http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/ . Wenn Sie jedoch selbst damit spielen, werden Sie feststellen, dass Sie wirklich Sprachunterstützung benötigen, wenn Sie all die coolen Dinge tun möchten - genau das hat Microsoft getan.
quelle
In dieser Geige https://dotnetfiddle.net/VhZdLU (und wenn möglich verbessern) können Sie eine einfache Konsolenanwendung ausführen, die die Verwendung von Task, Task.WaitAll (), asynchronen und wartenden Operatoren im selben Programm anzeigt .
Diese Geige sollte Ihr Ausführungszykluskonzept klären.
Hier ist der Beispielcode
Trace aus dem Ausgabefenster:
quelle
quelle
Auf einer höheren Ebene:
1) Das Schlüsselwort Async aktiviert das Warten und das ist alles, was es tut. Das Schlüsselwort Async führt die Methode nicht in einem separaten Thread aus. Die asynchrone Anfangsmethode wird synchron ausgeführt, bis sie auf eine zeitaufwändige Aufgabe wartet.
2) Sie können auf eine Methode warten, die Task oder Task vom Typ T zurückgibt. Sie können nicht auf eine asynchrone void-Methode warten.
3) In dem Moment, in dem Hauptthread-Begegnungen auf eine zeitaufwändige Aufgabe warten oder wenn die eigentliche Arbeit gestartet wird, kehrt der Hauptthread zum Aufrufer der aktuellen Methode zurück.
4) Wenn der Hauptthread auf eine Aufgabe wartet, die noch ausgeführt wird, wartet er nicht darauf und kehrt zum Aufrufer der aktuellen Methode zurück. Auf diese Weise bleibt die Anwendung reaktionsschnell.
5) Warten auf Verarbeitungsaufgabe, wird jetzt auf einem vom Thread-Pool getrennten Thread ausgeführt.
6) Wenn diese Warteaufgabe abgeschlossen ist, wird der gesamte darunter liegende Code vom separaten Thread ausgeführt
Unten ist der Beispielcode. Führen Sie es aus und überprüfen Sie die Thread-ID
quelle
So wie ich es verstehe, sollte der Mischung auch ein dritter Begriff hinzugefügt werden :
Task
.Async
ist nur ein Qualifikationsmerkmal, das Sie Ihrer Methode hinzufügen, um zu sagen, dass es sich um eine asynchrone Methode handelt.Task
ist die Rückgabe derasync
Funktion. Es wird asynchron ausgeführt.Sie
await
eine Aufgabe. Wenn die Codeausführung diese Zeile erreicht, springt die Steuerung zurück zum Aufrufer Ihrer umgebenden ursprünglichen Funktion.Wenn Sie stattdessen die Rückgabe einer
async
Funktion (dhTask
) einer Variablen zuweisen und die Codeausführung diese Zeile erreicht, wird sie in der umgebenden Funktion nur über diese Zeile hinaus fortgesetzt , während dieTask
asynchrone Ausführung ausgeführt wird.quelle
Dieser Artikel MDSN: Asynchrone Programmierung mit asynchronem und warten (C #) erklärt es explizit:
quelle
Im folgenden Code gibt die HttpClient-Methode GetByteArrayAsync die Aufgabe getContentsTask zurück. Die Aufgabe ist ein Versprechen, das tatsächliche Byte-Array zu erzeugen, wenn die Aufgabe abgeschlossen ist. Der Operator await wird auf getContentsTask angewendet, um die Ausführung in SumPageSizesAsync anzuhalten, bis getContentsTask abgeschlossen ist. In der Zwischenzeit wird die Kontrolle an den Aufrufer von SumPageSizesAsync zurückgegeben. Wenn getContentsTask beendet ist, wird der Ausdruck await zu einem Byte-Array ausgewertet.
quelle
Unten finden Sie Code, der die Excel-Datei durch Öffnen des Dialogfelds liest und dann asynchron verwendet. Warten Sie, bis der Code asynchron ausgeführt wird, der eine Zeile nach der anderen aus Excel liest und an das Raster bindet
quelle
Die Antworten hier sind als allgemeine Anleitung zum Warten / Asynchronisieren nützlich. Sie enthalten auch einige Details darüber, wie das Warten / Asynchronisieren verkabelt ist. Ich möchte einige praktische Erfahrungen mit Ihnen teilen, die Sie kennen sollten, bevor Sie dieses Entwurfsmuster verwenden.
Der Begriff "Warten" ist wörtlich, sodass jeder Thread, den Sie aufrufen, auf das Ergebnis der Methode wartet, bevor Sie fortfahren. Im Vordergrund ist dies eine Katastrophe . Der Vordergrund-Thread trägt die Last der Erstellung Ihrer App, einschließlich Ansichten, Ansichtsmodellen, anfänglichen Animationen und allem, was Sie sonst noch mit diesen Elementen gebootet haben. Wenn Sie also auf den Vordergrund-Thread warten, stoppen Sie die App. Der Benutzer wartet und wartet, wenn nichts zu passieren scheint. Dies bietet eine negative Benutzererfahrung.
Sie können einen Hintergrund-Thread mit einer Vielzahl von Mitteln abwarten:
Der vollständige Code für diese Bemerkungen befindet sich unter https://github.com/marcusts/xamarin-forms-annoyances . Siehe die Lösung mit dem Namen AwaitAsyncAntipattern.sln.
Die GitHub-Site enthält auch Links zu einer ausführlicheren Diskussion zu diesem Thema.
quelle
async / await
weiß , ist syntaktischer Zucker für Rückrufe nichts mit Threading zu tun. msdn.microsoft.com/en-us/magazine/hh456401.aspx Dies gilt für nicht CPU-gebundenen Code, z. B. Warten auf Eingabe oder Verzögerung.Task.Run
sollte nur für CPU-gebundenen Code verwendet werden blog.stephencleary.com/2013/10/…The term "await" is literal, so whatever thread you call it on will wait for the result of the method before continuing.
Dies ist nicht wahr - vielleicht meinten Sie Task.Wait ()? Wenn Sie verwendenawait
, wird der Rest der Methode als Fortsetzung festgelegt, die ausgeführt werden soll, wenn alles, was Sie erwartet haben, abgeschlossen ist. Es beendet die Methode, in der Sie es verwendet haben, damit der Anrufer fortfahren kann. Wenn die erwartete Zeile dann tatsächlich vollständig ist, wird der Rest dieser Methode für einen Thread (normalerweise einen Arbeitsthread) abgeschlossen.async/await
darum , .NET-Threads freizugeben . Wenn Sieawait
eine wirklich asynchrone Operation ausführen (z. B. File.WriteAsync von .NET), wird der Rest der von Ihnen verwendeten Methode angehaltenawait
, sodass der Aufrufer fortfahren und möglicherweise seinen Zweck beenden kann. Es wird kein Thread blockiert oder auf dieawait
Operation -ed gewartet . Wenn der von Ihnenawait
bearbeitete Vorgang abgeschlossen ist, wird der Rest derasync/await
Methode in einen Thread gestellt und ausgeführt (ähnlich einer Rückrufidee).