Cuando usa async
/ await
, no hay garantía de que el método al que llama cuando lo haga await FooAsync()
realmente se ejecute de forma asincrónica. La implementación interna es libre de regresar utilizando una ruta completamente sincrónica.
Si está haciendo una API donde es crítico que no bloquee y ejecute algún código de forma asincrónica, y existe la posibilidad de que el método llamado se ejecute sincrónicamente (bloqueo efectivo), el uso await Task.Yield()
obligará a su método a ser asíncrono y devolverá control en ese punto. El resto del código se ejecutará más adelante (en ese momento, aún puede ejecutarse sincrónicamente) en el contexto actual.
Esto también puede ser útil si realiza un método asincrónico que requiere una inicialización de "ejecución prolongada", es decir:
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);
}
Sin la Task.Yield()
llamada, el método se ejecutará sincrónicamente hasta la primera llamada a await
.
await Task.Yield()
obliga al método a ser asíncrono, ¿por qué nos molestaría escribir código asincrónico "real"? Imagine un método de sincronización pesado. Para hacerlo asíncrono, simplemente agregueasync
yawait Task.Yield()
al principio y mágicamente, ¿será asíncrono? Eso sería más o menos como envolver todo el código de sincronizaciónTask.Run()
y crear un método asíncrono falso.Task.Run
para implementarlo,ExecuteFooOnUIThread
se ejecutará en el grupo de subprocesos, no en el subproceso de la interfaz de usuario. Conawait Task.Yield()
, lo fuerza a ser asíncrono de manera que el código posterior todavía se ejecute en el contexto actual (solo en un momento posterior). No es algo que normalmente haría, pero es bueno que exista la opción si es necesario por alguna extraña razón.ExecuteFooOnUIThread()
durara mucho tiempo, aún bloquearía el hilo de la interfaz de usuario durante un tiempo prolongado en algún momento y haría que la interfaz de usuario no respondiera, ¿es correcto?