Ich habe dies verfolgt Frage und ich verstehe die Gründe für die populäre (wenn auch noch nicht akzeptierte) Antwort von Peter Duniho . Insbesondere ist mir bewusst, dass not , das auf eine nachfolgende lang andauernde Operation wartet, den UI-Thread blockiert:
Das zweite Beispiel gibt während des asynchronen Vorgangs nicht nach. Stattdessen erzwingen Sie durch Abrufen des Werts der Eigenschaft content.Result den aktuellen Thread, bis der asynchrone Vorgang abgeschlossen ist.
Ich habe das sogar bestätigt, zu meinem eigenen Vorteil, so:
%Vor% Aber jetzt frage ich mich: Müssen Sie await
alle "erwarteten" Operationen verschachtelt in einer äußersten erwarteten Operation? Zum Beispiel kann ich das tun:
Oder ich kann das tun:
%Vor%Und keiner von ihnen friert die Benutzeroberfläche ein. Welches ist vorzuziehen?
Der letzte ist vorzuziehen (obwohl ziemlich chaotisch)
In TAP (aufgabenbasiertes asynchrones Muster) Eine Aufgabe (und andere erwartete) stellen eine asynchrone Operation dar. Sie haben grundsätzlich 3 Möglichkeiten, diese Aufgaben zu bearbeiten:
DoAsync().Result
, DoAsync().Wait()
) - Blockiert den aufrufenden Thread, bis die Aufgabe abgeschlossen ist. Macht Ihre Anwendung verschwenderischer, weniger skalierbar, weniger reaktiv und anfällig für Deadlocks. await DoAsync()
) - Blockiert den aufrufenden Thread nicht. Es registriert im Grunde die Arbeit nach dem await
als eine Fortsetzung, die ausgeführt wird, nachdem die erwartete Aufgabe abgeschlossen ist. DoAsync()
) - Blockiert nicht den aufrufenden Thread, sondern wartet auch nicht auf den Abschluss des Vorgangs. Sie sind sich keiner Ausnahmen bewusst, die ausgelöst werden, während DoAsync
verarbeitet wird Insbesondere ist mir bewusst, dass das Warten auf einen nachfolgenden lang andauernden Vorgang den UI-Thread nicht blockiert
Also, nicht ganz. Wenn Sie überhaupt nicht warten, wird nichts blockiert, aber Sie können nicht wissen, wann oder ob der Vorgang erfolgreich abgeschlossen wurde. Wenn Sie jedoch synchron warten, blockieren Sie den aufrufenden Thread und Sie haben möglicherweise Deadlocks, wenn Sie den UI-Thread blockieren.
Fazit: Du solltest await
auf deine Erwartungswerte warten, solange dies möglich ist (zum Beispiel nicht in Main
). Dazu gehören "verschachtelte async-await
-Operationen".
Über dein spezifisches Beispiel: Task.Run
wird verwendet, um CPU-gebundene Arbeit in einen ThreadPool
-Thread zu verschieben, was nicht das zu sein scheint, was du nachahmen willst. Wenn wir Task.Delay
verwenden, um eine wirklich asynchrone Operation darzustellen (normalerweise I / O-gebunden), können wir " async-await
" verschachtelt haben ohne Task.Run
:
Sie können anonyme Delegaten statt Methoden verwenden, aber es ist unangenehm, wenn Sie die Typen definieren und selbst aufrufen müssen.
Wenn Sie diese Operation in einen ThreadPool
-Thread auslagern müssen, fügen Sie einfach Task.Run
:
Tags und Links .net c# task-parallel-library async-await asynchronous