Wie kann ich warten, bis eine void async
Methode ihren Job beendet hat?
Zum Beispiel habe ich eine Funktion wie unten:
async void LoadBlahBlah()
{
await blah();
...
}
Jetzt möchte ich sicherstellen, dass alles geladen wurde, bevor ich woanders weitermache.
c#
asynchronous
MBZ
quelle
quelle
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
ist irreführend. Dies wartet nicht auf den Abschluss der asynchronen Funktionblah
, sondern nur auf die (triviale) Erstellung der Aufgabe und wird unmittelbar vorblah()
Abschluss fortgesetzt .Thread.Sleep
nicht asynchron. Bei dieser Frage geht es darum, auf eineasync void
Veranstaltung zu warten , sagen wirasync void blah() { Task.Delay(10000); }
Wenn Sie die Signatur Ihrer Funktion in ändern können, können
async Task
Sie den hier dargestellten Code verwendenquelle
Die beste Lösung ist zu verwenden
async Task
. Sie solltenasync void
aus mehreren Gründen vermeiden , von denen einer die Kompositionsfähigkeit ist.Wenn die Methode nicht zurückgegeben werden kann
Task
(z. B. ein Ereignishandler), können SieSemaphoreSlim
das Methodensignal verwenden, wenn es beendet werden soll. Betrachten Sie dies in einemfinally
Block.quelle
Führen Sie ein AutoResetEvent durch, rufen Sie die Funktion auf, warten Sie auf AutoResetEvent und setzen Sie es dann in async void, wenn Sie wissen, dass es fertig ist.
Sie können auch auf eine Aufgabe warten, die von Ihrem ungültigen Async zurückkehrt
quelle
Sie müssen eigentlich nichts manuell tun, das
await
Schlüsselwort pausiert die Funktionsausführung, bis esblah()
zurückkehrt.T
ist die Art derblah()
ObjektrückgabeSie können nicht wirklich
await
einevoid
Funktion sein, alsoLoadBlahBlah()
kann es nicht seinvoid
quelle
LoadBlahBlah()
bis ich fertig bin , nichtblah()
Ich weiß, dass dies eine alte Frage ist, aber dies ist immer noch ein Problem, auf das ich immer wieder stoße, und dennoch gibt es keine klare Lösung, um dies korrekt zu tun, wenn async / await in einer asynchronen Void-Signaturmethode verwendet wird.
Ich habe jedoch festgestellt, dass .Wait () innerhalb der void-Methode ordnungsgemäß funktioniert.
und da async void und void dieselbe Signatur haben, müssen Sie möglicherweise Folgendes tun.
Verwirrenderweise blockiert async / await den nächsten Code nicht.
Wenn Sie Ihren Code dekompilieren, schätze ich, dass async void eine interne Aufgabe erstellt (genau wie asynchrone Aufgabe), aber da die Signatur die Rückgabe dieser internen Aufgaben nicht unterstützt
Dies bedeutet, dass die asynchrone void-Methode intern weiterhin intern asynchrone Methoden "abwarten" kann. aber extern nicht in der Lage zu wissen, wann die interne Aufgabe abgeschlossen ist.
Mein Fazit ist also, dass die asynchrone Leere wie beabsichtigt funktioniert. Wenn Sie Feedback von der internen Aufgabe benötigen, müssen Sie stattdessen die Signatur der asynchronen Aufgabe verwenden.
hoffentlich macht mein Streifzug Sinn für jeden, der auch nach Antworten sucht.
Bearbeiten: Ich habe einen Beispielcode erstellt und ihn dekompiliert, um zu sehen, was tatsächlich vor sich geht.
Wird zu (bearbeiten: Ich weiß, dass der Body-Code nicht hier, sondern in den Statemaschinen ist, aber die Statemaschinen waren im Grunde identisch, also habe ich mich nicht darum gekümmert, sie hinzuzufügen)
Weder AsyncVoidMethodBuilder noch AsyncTaskMethodBuilder enthalten tatsächlich Code in der Start-Methode, der darauf hinweist, dass sie blockiert werden sollen, und der nach dem Start immer asynchron ausgeführt wird.
Das heißt, ohne die zurückgebende Aufgabe gibt es keine Möglichkeit zu überprüfen, ob sie abgeschlossen ist.
Wie erwartet wird nur die asynchrone Task gestartet und anschließend im Code fortgesetzt. und die asynchrone Aufgabe, zuerst startet sie die Aufgabe und gibt sie dann zurück.
Ich denke, meine Antwort wäre, niemals asynchrone Leere zu verwenden. Wenn Sie wissen müssen, wann die Aufgabe erledigt ist, ist dies die Aufgabe der asynchronen Aufgabe.
quelle