Das Problem beim Aufruf von async void ist, dass
erhalten Sie nicht einmal die Aufgabe zurück. Sie haben keine Möglichkeit zu wissen, wann die Aufgabe der Funktion abgeschlossen ist. -- Crashkurs in async und await | The Old New Thing
Hier sind die drei Möglichkeiten, eine asynchrone Funktion aufzurufen:
async Task<T> SomethingAsync() { ... return t; }
async Task SomethingAsync() { ... }
async void SomethingAsync() { ... }
In allen Fällen wird die Funktion in eine Kette von Aufgaben umgewandelt. Der Unterschied besteht darin, was die Funktion zurückgibt.
Im ersten Fall gibt die Funktion eine Aufgabe zurück, die schließlich das t erzeugt.
Im zweiten Fall gibt die Funktion eine Aufgabe zurück, die kein Produkt hat, aber Sie können aber Sie können trotzdem auf sie warten, um zu erfahren, wann sie abgeschlossen ist.
Der dritte Fall ist der unangenehme. Der dritte Fall ist wie der zweite Fall, außer dass dass Sie nicht einmal die Aufgabe zurückbekommen. Sie haben keine Möglichkeit zu wissen, wann die Aufgabe der Funktion abgeschlossen ist.
Der async void Fall ist ein "Feuer und vergessen": Man startet die Aufgabenkette, aber man kümmert sich nicht darum, wann sie abgeschlossen ist. beendet ist. Wenn die Funktion zurückkehrt, wissen Sie nur, dass alles bis zum ersten await ausgeführt wurde. Alles nach dem ersten await wird zu einem unbestimmten Zeitpunkt in der Zukunft ausgeführt, auf den Sie keinen zu dem Sie keinen Zugang haben.
47 Stimmen
@Fred Meistens, aber nicht immer. Dies ist nur die Konvention und die akzeptierten Ausnahmen von dieser Konvention sind ereignisbasierte Klassen oder Schnittstellenverträge, siehe MSDN . So sollten Sie beispielsweise gängige Ereignis-Handler wie Button1_Click nicht umbenennen.
18 Stimmen
Nur eine Anmerkung, die Sie nicht verwenden sollten
Thread.Sleep
mit Ihren Aufgaben sollten Sieawait Task.Delay(num)
stattdessen78 Stimmen
@fred Ich stimme damit nicht überein, IMO Hinzufügen einer async Suffix sollte nur verwendet werden, wenn Sie eine Schnittstelle mit sowohl sync und async Optionen bereitstellen. Dinge mit async zu benennen, wenn es nur eine Absicht gibt, ist sinnlos. Beispiel
Task.Delay
ist nichtTask.AsyncDelay
da alle Methoden der Aufgabe Async sind18 Stimmen
Ich hatte ein interessantes Problem heute Morgen mit einem webapi 2 Controller-Methode, es wurde als deklariert
async void
stattdessenasync Task
. Die Methode stürzte ab, weil sie ein Entity Framework-Kontextobjekt verwendete, das als Mitglied des Controllers deklariert war und entsorgt wurde, bevor die Methode zur Ausführung kam. Das Framework hat den Controller entsorgt, bevor seine Methode ausgeführt wurde. Ich änderte die Methode in async Task und es funktionierte.2 Stimmen
Ich denke dieser Link hilft.