19/07/2013

[WindowsPhone] WebClient et async await pattern

Bonjour à toutes et à tous
aujourd'hui je fais une suite à l'article ici sur la mise place du pattern async await (Nouveauté C# 5) avec un WebClient.

WebClientExtensions

Comme je l'avais annoncé dans l'article précédent, il n'est pas possible en l'état d'utiliser un WebClient avec le pattern async await. Du coup, on va voir aujourd'hui comment contourner cela.

Alors le premier point est de comprendre pourquoi cela ne marche pas. Tout simplement car la méthode DownloadStringAsync ne renvois pas de Task nécessaire au await.

Donc pour contourner cette limitation nous allons, dans la partie liée au services, créer un classe supplémentaire qui va venir surchager notre WebClient et lui faire renvoyer une Task.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace System.Threading.Tasks
{
    public static class WebClientExtensions
    {

        public static Task<string> DownloadStringTaskAsync(this WebClient webClient, Uri address)
        {
            var taskCSource = new TaskCompletionSource<string>();

            webClient.DownloadStringCompleted += (s, e) =>
            {
                if (e.Error != null)
                {
                    taskCSource.SetException(e.Error);
                }
                else
                {
                    taskCSource.SetResult(e.Result);
                }
            };

            webClient.DownloadStringAsync(address);

            return taskCSource.Task;
        }

        public static Task<string> DownloadStringTaskAsync(this WebClient webClient, string address)
        { 
            return DownloadStringTaskAsync(webClient, new Uri(address));
        }
    }
}

Si vous recréez cette classe, prenez garde au namespace, il est important ! Donc dans la première méthode, on instancie notre TaskCompletionSource on s'abonne à l'événement DownloadStringCompleted et on utilise un delagate pour assignes Exception et Result à notre tâche. Enfin on lance de téléchargement et on retourne la Task.
La seconde méthode est simplement une surcharge au cas où vous souhaiteriez lancer la même méthode avec un string plutôt qu'une Uri.

Conclusion

Voilà c'est tout pour aujourd'hui, comme d'habitude vous pouvez retrouver les sources ici

Aucun commentaire:

Enregistrer un commentaire