without whenall method httpresponsemessage explained ejemplo create await async c# async-await

whenall - task httpresponsemessage c#



¿Cuándo usaría Task.Yield()? (4)

Cuando utiliza async / await , no hay garantía de que el método que llama cuando await FooAsync() se ejecutará de manera asíncrona. La implementación interna es gratuita para regresar usando una ruta completamente sincrónica.

Si está creando una API donde es fundamental que no bloquee y ejecute código de forma asíncrona, y existe la posibilidad de que el método invocado se ejecute de forma síncrona (bloqueando efectivamente), con await Task.Yield() forzará su método ser asíncrono y devolver el control en ese punto. El resto del código se ejecutará en un momento posterior (en ese punto, aún puede ejecutarse sincrónicamente) en el contexto actual.

Esto también puede ser útil si realiza un método asíncrono que requiere una inicialización de "larga ejecución", 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 llamada Task.Yield() , el método se ejecutará sincrónicamente hasta la primera llamada en await .

Estoy usando async / await y Task mucho, pero nunca he usado Task.Yield() y, para ser sincero, incluso con todas las explicaciones, no entiendo por qué necesitaría este método.

¿Alguien puede dar un buen ejemplo donde se requiere Yield() ?


Internamente, await Task.Yield() simplemente await Task.Yield() cola la continuación en el contexto de sincronización actual o en un hilo de grupo aleatorio, si SynchronizationContext.Current es null .

Se implementa de manera eficiente como awaiter personalizado. Un código menos eficiente que produzca el mismo efecto podría ser tan simple como esto:

var tcs = new TaskCompletionSource<bool>(); var sc = SynchronizationContext.Current; if (sc != null) sc.Post(_ => tcs.SetResult(true), null); else ThreadPool.QueueUserWorkItem(_ => tcs.SetResult(true)); await tcs.Task;

Task.Yield() se puede utilizar como atajo para algunas alteraciones de flujo de ejecución extrañas. Por ejemplo:

async Task DoDialogAsync() { var dialog = new Form(); Func<Task> showAsync = async () => { await Task.Yield(); dialog.ShowDialog(); } var dialogTask = showAsync(); await Task.Yield(); // we''re on the dialog''s nested message loop MessageBox.Show("The dialog is visible, click OK to close"); dialog.Close(); await dialogTask; // we''re back to the main message loop }

Dicho esto, no puedo pensar en ningún caso donde Task.Yield() no pueda ser reemplazado por Task.Factory.StartNew con el programador de tareas adecuado.

Ver también:


Tengo una clase base que tiene un método principal:

public async Task SendAsync (message);

Luego decidí en una fecha posterior que quería auditar el mensaje enviado en una variante más avanzada de la clase base, a lo que agregué dos métodos básicos:

protected virtual async Task OnBeforeSend(message); protected virtual async Task OnAfterSend(message);

En la versión especializada de mi clase, agregué implementaciones a los métodos de envío de mensajes antes y después, pero no necesité agregar métodos de envío antes y después personalizados a la implementación de mi clase base. Exigí que mi implementación base también fuera de tipo concreto ya que se estaba utilizando en otros lugares.

Para mantener feliz al compilador, necesitaba proporcionar un resultado de la tarea para las implementaciones básicas (vacías) y para esto he usado el enfoque Task.Yield (). Por lo tanto, en mi implementación de la clase base tengo esto:

protected virtual async Task OnBeforeSend(IEmailMessage mailMessage) { await Task.Yield(); }

Parece funcionar bien para mí y no puedo ver una razón por la cual esto sería incorrecto.


Task.Yield() se puede usar en implementaciones simuladas de métodos asíncronos.