Async/Await для .Net 4.0

Сложность 200-400

Буквально на днях в блоге разработчиков Base Class Library промелькнуло известие о том, что теперь можно использовать async/await и для кода написанного на .Net Framework 4. А это значит можно использовать удобный подход для асинхронной работы, даже если пользователи вашей программы до сих пор сидят на «старой, доброй XP» по тем или иным причинам. Естественно такая новость не могла пройти мимо меня, чтобы я не попробовал как оно на самом деле в использовании. Забегая вперед, и что вполне ожидаемо, работает все точно так же как и в 4.5 за исключением некоторых нюансов в процессе разработки. Но обо всем по порядку.

Команда разработчиков анонсировала пакет дополнений, который позволяет использовать await в Visual Studio 2012 (в предыдущих версиях работать не будет). Выпущенный пакет может быть применен к следующим платформам (указанной версии или выше):

  • .NET Framework 4.0 (with KB2468871)
  • Silverlight 4
  • Windows Phone 7.5
  • И портируемые библиотеки опирающиеся на указанные платформы.

Т.е. это не встроенная фича .net 4.5?

И да и нет. Очень заманчиво думать, что новые ключевые слова await/async в C# являются чистым новым функционалом языка. В некоторой степени это так: компилятору необходимо проделать достаточно много сложной работы с вашим кодом, чтобы он мог ожидать операции.

Принимая вышесказанное во внимание, разработчики ожидают возможность использования await как только они переходят на новую студию – независимо от платформы языка. Если вы задумывались о том, как реализовано большинство фич языка, то вы можете догадаться, что многие вещи не просто данность и особенность языка. Множество конструкций языка опираются на вполне конкретные API, к примеру, методы расширения опираются на ExtensionAttribute, а foreach зависит от интерфейса IEnumerable. В случае с await потребуется давно любимый класс Task и некоторая хитрая обвязка, которая делает возможным использование await.

Подключение

Для того, чтобы использовать функционал await/async требуется 2 компонента:

  • Visual Studio 2012
  • Некоторое специфичное .Net API

Как вы уже наверно поняли, это специфичное API распространяется в виде NuGet пакета. Пока что пакет идет как Prerelease, так что потребуется дополнительный ключ –pre

 

Естественно, что есть некоторые ограничения и, возможно, у вас будут проблемы, которые описаны в специальном документе.

Практика

В качестве закрепления материала и демонстрации, что все реально и возможно, а так же как оно работает, посмотрим на такой код:

Сначала разберем код с теоретической точки зрения. Я хочу, чтобы надписи вывелись в ожидаемом порядке выполнения. Т.е. сначала о том, что сервис стартанул, потом что метод начался, метод закончился, и что сервис закончил работу. Для консольного приложения не сильно видна многопоточность, если использовать только один этот метод, но если в методе Main() считывать знаки введенные пользователем, то вы увидите разницу. Можно подумать, что в данном случае await выступает в скорее роли Task.Wait(), но при использовании этого метода «в лоб» не будет желаемого результата, так как метод получится синхронным. Для ожидаемой работы и в записывая код в более традиционном виде все выглядит так:

Т.е. надо выделять дополнительный метод для обратного вызова.

Если вы работаете с ReSharper, то он не будет помогать вам с новой библиотекой и будет всячески смущать вас комментариями о том, что класс Task не может быть awaitable, что неправда.

Таким образом вам придется смириться с этим неудобством на некоторое время, пока JetBrains не выпустят обновление для R#. По крайней мере я надеюсь на это обновление.

При просмотре полученного кода в декомпиляторе DotPeak можно увидеть, что код абсолютно идентичен, строка в строку. Это к вопросу о фичах языка.

Итак, жизнь становится проще и веселее с возможностью использовать async\await в приложениях для .Net 4.0. Как всегда, я надеюсь, что время потраченное на прочтение статьи оказалось для вас полезным и вы вынесли для себя что-то новое.

 

 

Hard’n’Heavy!

 

Оставить комментарий