Wenn Sie async
/ verwenden await
, gibt es keine Garantie dafür, dass die Methode, die Sie dabei aufrufen await FooAsync()
, tatsächlich asynchron ausgeführt wird. Die interne Implementierung kann über einen vollständig synchronen Pfad zurückgegeben werden.
Wenn Sie eine API erstellen, bei der es wichtig ist, dass Sie nicht blockieren und Code asynchron ausführen, und die aufgerufene Methode await Task.Yield()
möglicherweise synchron ausgeführt wird (effektiv blockiert), erzwingt die Verwendung, dass Ihre Methode asynchron ist, und kehrt zurück Kontrolle an diesem Punkt. Der Rest des Codes wird zu einem späteren Zeitpunkt (zu diesem Zeitpunkt wird er möglicherweise noch synchron ausgeführt) im aktuellen Kontext ausgeführt.
Dies kann auch nützlich sein, wenn Sie eine asynchrone Methode erstellen, die eine "lang laufende" Initialisierung erfordert, z.
private async void button_Click(object sender, EventArgs e)
{
await Task.Yield(); // Make us async right away
var data = ExecuteFooOnUIThread(); // This will run on the UI thread at some point later
await UseDataAsync(data);
}
Ohne den Task.Yield()
Aufruf wird die Methode bis zum ersten Aufruf von synchron ausgeführt await
.
await Task.Yield()
die Methode asynchron sein soll, warum sollten wir uns dann die Mühe machen, "echten" asynchronen Code zu schreiben? Stellen Sie sich eine schwere Synchronisationsmethode vor. Um es asynchron zu machen, fügen Sie einfach hinzuasync
undawait Task.Yield()
am Anfang und auf magische Weise wird es asynchron sein? Das wäre so ziemlich so, als würde man den gesamten Synchronisierungscode einpackenTask.Run()
und eine gefälschte asynchrone Methode erstellen.Task.Run
, um es zu implementieren,ExecuteFooOnUIThread
wird es im Thread-Pool ausgeführt, nicht im UI-Thread. Mitawait Task.Yield()
erzwingen Sie, dass es so asynchron ist, dass der nachfolgende Code immer noch im aktuellen Kontext ausgeführt wird (nur zu einem späteren Zeitpunkt). Es ist nicht etwas, was Sie normalerweise tun würden, aber es ist schön, dass es die Option gibt, wenn es aus irgendeinem seltsamen Grund erforderlich ist.ExecuteFooOnUIThread()
es sehr lange laufen würde, würde es den UI-Thread irgendwann noch für eine lange Zeit blockieren und die UI nicht mehr reagieren lassen. Ist das richtig?Intern müssen Sie
await Task.Yield()
die Fortsetzung einfach entweder im aktuellen Synchronisationskontext oder in einem zufälligen Pool-Thread in die Warteschlange stellen, falls dies der FallSynchronizationContext.Current
istnull
.Es wird effizient als benutzerdefinierter Kellner implementiert. Ein weniger effizienter Code, der den identischen Effekt erzeugt, könnte so einfach sein:
Task.Yield()
kann als Abkürzung für einige seltsame Änderungen des Ausführungsflusses verwendet werden. Beispielsweise:Das heißt, ich kann mir keinen Fall
Task.Yield()
vorstellen, in dem nicht durch einenTask.Factory.StartNew
richtigen Taskplaner ersetzt werden kann.Siehe auch:
"warte auf Task.Yield ()" und seine Alternativen
Task.Yield - echte Verwendungen?
quelle
var dialogTask = await showAsync();
?var dialogTask = await showAsync()
wird nicht kompiliert, da derawait showAsync()
Ausdruck kein a zurückgibtTask
(im Gegensatz zu ohneawait
). Wenn Sie dies jedoch tunawait showAsync()
, wird die Ausführung nach dem Schließen des Dialogfelds erst wieder aufgenommen. So ist es anders. Das liegt daran, dasswindow.ShowDialog
es sich um eine synchrone API handelt (obwohl sie immer noch Nachrichten pumpt). In diesem Code wollte ich fortfahren, während der Dialog noch angezeigt wird.Eine Verwendung
Task.Yield()
besteht darin, einen Stapelüberlauf zu verhindern, wenn eine asynchrone Rekursion durchgeführt wird.Task.Yield()
verhindert synchrone Fortsetzung. Beachten Sie jedoch, dass dies eine OutOfMemory-Ausnahme verursachen kann (wie von Triynko angegeben). Endlose Rekursion ist immer noch nicht sicher und Sie sollten die Rekursion wahrscheinlich besser als Schleife umschreiben.quelle
await Task.Delay(1)
ausreicht, um es zu verhindern. (Konsolen-App, .NET Core 3.1, C # 8)Task.Yield()
kann in Scheinimplementierungen von asynchronen Methoden verwendet werden.quelle