- PVSM.RU - https://www.pvsm.ru -
У вас проект на .NET 4.0 и вам надоела «лапша» из колбеков? Вы бы хотели использовать async/await в своем проекте, но тимлид грозит небесной карой за смену платформы? Если установка патча на фреймворк и студию для вас являются допустимым решением, то вам сюда [1]. Если нет, то существует другое решение.
Async-метод это сопрограмма [2], которая выходит на каждом await, и восстанавливается с этой точки по завершению ожидания(автор знает [3], что выполнение не всегда прерывается на await и что «ожидать» можно не только экземпляры Task). Итак, начиная со второй версии дотнета можно легко создавать сопрограммы с помощью ключевого слова yield. Этим инструментом мы и воспользуемся.
Хочется писать как на C# 5.0, и при этом не ставить никаких языковых расширений. К сожалению так не получится. Но есть вот такой вариант:
private IEnumerable Login(...)
{
// ...
// get user id, if not specified
if (string.IsNullOrEmpty(uid))
{
var getUserIdTask = сlient.GetUserId(...); yield return getUserIdTask; // await
uid= getUserIdTask.Result.uid;
}
// login
var loginTask = сlient.Login(...); yield return loginTask; // await
var sessionId = loginTask.Result.SessionId;
// getting user's profile
var getUserInfoTask = сlient.GetUserInfo(...); yield return getUserInfoTask; // await
var userInfo = getUserInfoTask.Result;
// ...
yield return userInfo; // return
}
Всё что возвращается через yield return и не является наследником Task считается результатом исполнения async-метода.
Код лежит тут [4].
Механизм работы простой:
Во всех вариантах завершения на итераторе будет вызван Dispose, что приведет к освобождению ресурсов в блоках using и try/finally.
Начать новую асинхронную задачу можно вызвав метод FromIterator:
private IEnumerable Login(...) { ... }
Task loginTask = TaskUtils.FromIterator(this.Login(...));
// или с возвращаемым значением
Task<UserInfo> loginTask = TaskUtils.FromIterator<UserInfo>(this.Login(...));
Опционально можно указать:
Большую часть минусов можно побороть тем или иным способом.
Ошибки по тексту можно направлять в ЛС.
Исходный код [4].
Автор: shai_hulud
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/30781
Ссылки в тексте:
[1] сюда: http://blogs.msdn.com/b/bclteam/archive/2012/10/22/using-async-await-without-net-framework-4-5.aspx
[2] сопрограмма: http://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B0
[3] знает: http://blogs.msdn.com/b/pfxteam/archive/2013/01/28/psychic-debugging-of-async-methods.aspx
[4] тут: http://pastebin.com/s23gWEzj
[5] Task.AsyncState: http://msdn.microsoft.com/ru-ru/library/system.threading.tasks.task.asyncstate.aspx
[6] TaskCreationOptions: http://msdn.microsoft.com/ru-ru/library/system.threading.tasks.taskcreationoptions.aspx
[7] Источник: http://habrahabr.ru/post/174799/
Нажмите здесь для печати.