[ windows phone 7 ] Using async and await

Использование async и await в WP7 / WP8

Долгое время я отказывался от их использования, т.к. в WP7 без сторонних библиотек это не работает, да и включать их, когда уже всё протестировано и написано по старинке, как-то не хотелось. И вот момент настал.

Зачем это вообще надо? В общем случае, чтобы избавиться от множественных Callback и упростить код, по сути, это так любимый многими в .NET синтаксический сахар.

В WP8 всё это чудо работает из коробки, в WP7 необходимо подключить через NuGet Microsoft.Bcl.Async

Пример запроса списка треков из vk.com:

    public static class VKapi
    {
        private static string _token;
        private static string _uid;
        public static void Init(string token, string userid)
        {
            _token = token;
            _uid = userid;
        }

        public async static Task<ObservableCollection<Track>> GetList()
        {
            WebClient w = CreateWebClient();
            Task<string> task = w.UploadStringTaskAsync(new Uri("https://api.vk.com/method/audio.get"), "POST", "owner_id=" + _uid + "&need_user=0&count=0&v=4.99" + "&access_token=" + _token);

            string result=await ProcessAsync(task);
            var corrected = System.Text.RegularExpressions.Regex.Replace(result, @"(?<=response\D*)\d[^{]*", string.Empty);
            return Deserialise<MusicCollection>(corrected).data;
        }

        async static Task<string> ProcessAsync(Task<string> task)
        {
            await TaskEx.WhenAny(task);
            if (task.Exception == null)
            {
                if (task.Result.StartsWith("{\"error\"")) // Стоит помнить, что ошибки нужно корректно обрабатывать
                    return null;
                System.Diagnostics.Debug.WriteLine("{SUCCESS REQUEST}");
                return task.Result;
            }
            else
            {
                System.Diagnostics.Debug.WriteLine("{ERROR REQUEST: } " + task.Exception.Message);
                return null;
            }

        }

        public static T Deserialise<T>(string json)
        {
            T obj = Activator.CreateInstance<T>();
            using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
                obj = (T)serializer.ReadObject(stream);

                return obj;
            }
        }

        private static WebClient CreateWebClient()
        {
            WebClient client = new WebClient();
            client.Headers["Accept"] = "*/*";
            client.Headers["code"] = "asO1pjUgf4TnLQFn3ylh";
            client.Headers["Content-Type"] = "application/x-www-form-urlencoded";

            return client;
        }
    }

Пример того, как мы этим пользуемся:

    [DataContract]
    public class MusicCollection
    {
        [DataMember(Name="response")]
        public ObservableCollection<Track> data { get; set; }

        public async Task<bool> GetVKdata()
        {
            data = await VKapi.GetList();
            if (data == null)
                return false;
            return true;
        }

    }

Никаких Callback, повышенная гибкость и разделение кода, сплошная радость.

Другие примеры и более подробная информация:

Async CTP – Task based asynchronous programming for Windows Phone

async, await and bit of windows phone

Класс Task на msdn

One Comment

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *