Использование 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
Вот ешё можно почитать:
http://developer.nokia.com/Community/Wiki/Asynchronous_Programming_For_Windows_Phone_8
http://msdn.microsoft.com/ru-ru/library/hh156528.aspx