Patrón async / await cuando tenemos eventos (EAP)


Cuando te acostumbras a usar await lo echas en falta si el API que usas no lo tiene. Esto mismo le pasó a Darío con el nuevo LiveSDK.

La buena noticia es que podemos encapsular en una Task nuestras llamadas asíncronas que usan el modelo basado en eventos (EAP).

En el caso de LiveSDK vamos a partir del ejemplo de Michael Crump. En él nos enseña a utilizar LiveSDK en una aplicación Metro de Windows 8, pero sigue utilizando el modelo EAP.

this.liveClient = new LiveConnectClient(e.Session);
session = e.Session;
this.liveClient.GetCompleted += OnGetCompleted;
this.liveClient.GetAsync("me", null);

Convertirlo al nuevo patrón asíncrono es bastante sencillo utilizando una combinación de Task y TaskCompletionSource, para hacerlo un poco más interesante lo escribiremos como método de extensión:

public static class LiveExtensions
{
    public static Task<IDictionary<string, object>>
        GetAsyncEx(this LiveConnectClient client, string path, object state)
    {
        var tcs = new TaskCompletionSource<IDictionary<string, object>>();
        client.GetCompleted += (o, e) =>
        {
            if (e.Error != null)
                tcs.SetException(e.Error);
            else
                tcs.SetResult(e.Result);
        };
        client.GetAsync(path, state);
        return tcs.Task;
    }
}

Una vez tenemos el método así escrito ya podemos usar await y reescribir el código original con un flujo mucho más claro 🙂

private async void btnLogIn_OnSessionChanged(object sender, 
    LiveConnectSessionChangedEventArgs e)
{
    if (e.Session != null && e.Status == LiveConnectSessionStatus.Connected)
    {
        this.liveClient = new LiveConnectClient(e.Session);
        session = e.Session;
        //this.liveClient.GetCompleted += OnGetCompleted;
        //this.liveClient.GetAsync("me", null);
        try
        {
            dynamic result = await this.liveClient.GetAsyncEx("me", null);
            this.tbName.Text = "Hello, " + result.first_name + " " + result.last_name;
            this.tbGender.Text = "You are a " + result.gender + " that lives in " + 
                result.locale + ".";
            this.tbLiveProfile.Text = "Your Live Profile can be found at: " + result.link;
        }
        catch (Exception ex)
        {
            this.tbError.Text = ex.ToString();
        }
    }
    else
    {
        this.liveClient = null;
    }
}

Para profundizar más sobre el patrón os recomiendo leer el documento que escribió Stephen Toub sobre el tema: Task-based Asynchronous Pattern (TAP).

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s