Автор: Sergey Teplyakov
Вчера я был на первом семинаре вообще и по .Net в частности и, так уж вышло, что вел этот семинар я (да, кроме меня, там тоже были люди, правда). Семинар был посвящен асинхронному программированию на платформе .Net, который состоялся вчера в учебном центре Люксофта.
Присутствовало где-то двадцать человек, большинство из которых это знакомые ребята из команд, в которых я либо работал, либо с которыми мы довольно тесно общаемся. Но человек 8 было и из других команд и, кажется, даже не из Люксофта. Благодаря тому, что в основном были все свои, атмосфера с самого начала была неформальной: ребята подкалывали меня, я, в свою очередь, их.
Семинар, по сути, был основан на основе двух моих статей по асинхронному программированию: Асинхронное программирование и AsyncEnumerator и Знакомство с асинхронными операциями в C# 5, а также статьи про внутреннее устройство итераторов: Итераторы в языке C#. Реактивные расширения, которые я тоже собрался рассмотреть, решительно не влезли, на рассмотрение только лишь RX-ов двух часов будет мало, так что я решил не распыляться.
В результате получилась презентация на 50 слайдов, примерно со следующей структурой:
1. Знакомство и всякое такое бла-бла-бла.
2. Синхронные операции с примерами, их достоинствами и недостатками.
Прежде чем переходить к асинхронному программированию, нужно понять, что не так с синхронным. В целом, большая часть народа с этими проблемами знакома, но рассказать о таких понятиях, как CPU-Bound и IO-Bound операции было полезно, чтобы все понимали, о чем пойдет речь.
3. Паттерны асинхронного программирования в .Net: (1) Classical Async Pattern и (2) Event-Based Async Pattern.
Практически каждый .Net программист знает о методах BeginXXX/EndXXX и большинство из них работали с классом BackgroundWorker. Однако не все знают, что методы BeginXXX/EndXXX представляют собой классический паттерн асинхронного программирования, а BackgroundWorker является типовым представителем Event-Based Async Pattern.
4. Недостатки существующих паттернов
Хотя это всего один слайд, но он достаточно важен, чтобы выделить его в отдельную секцию. Все же именно недостатки использования существующих паттернов асинхронного программирования, такие как сложность использования и извращение потока исполнения, сподвигли камрадов таких как Джеффа Рихтера и Эрика Мейера (Eric Meijer) придумывать всякую разную хрень, типа классов AsyncEnumerator и библиотек, типа Reactive Extensions. Я уже молчу за некоторых личностей, которые решили добавить поддержку асинхронности в пару весьма популярных языков программирования (*).
5. Библиотека PowerThreading и, в особенности, класс AsyncEnumerator.
Важность творения Рихтера заключается в том, что именно эта же идея лежит в основе новых языковых конструкций языка C# 5: await и async. Но, поскольку, этот класс построен на основе минимума дополнительных языковых конструкций и не использует никаких других сторонних библиотек, то разобраться с выпрямлением им потока исполнения значительно легче, нежели сразу же переходить к рассмотрению await и async. По сути, единственное понятие, которое нужно осилить это блоки итераторов.
5.1. Отвлечение от темы: блоки итераторов.
Я подозревал, что объяснить принцип работы класса AsyncEnumerator без понимания того, как работают блоки итераторов невозможно. И я, видимо, правильно сделал, что добавил этот раздел в доклад, многие ребята прекрасно знают, что такое блоки итераторов и более или менее представляют, как они устроены, но далеко не всем понятны последствия разрыва шаблона, которые устраивает yield return. На протяжении всего доклада я возвращался к теме итераторов и напоминал об их внутреннем устройстве.
6. Асинхронные операции в C# 5. Ключевые слова async и await.
Вот здесь я допустил, наверное, самую существенную ошибку: я слишком мало внимания уделил рассмотрению классов Task. По сути, новые фичи асинхронного программирования построены на основе двух концепций: (1) вывиху потока исполнения, которая очень напоминает блоки итераторов и (2) классах задач (Task и Task<,T>,). Но, более или менее подробно я рассмотрел только первую составляющую, а вторую рассмотрел лишь поверхностно. Поэтому пришлось на ходу приводить примеры с тасками, со всеми их продолжениями, контекстами синхронизации и взаимосвязи с BeginXXX/EndXXX и показывать их на пальцах.
Основное же рассмотрение возможностей await и async велось в контексте уже изученного материала: заменяем IEnumerator<,int>, на async, а yield return на await и мы переходим от AsyncEnumerator-а к новым возможностям C# 5.0.
7. Заключение, вопросы и т.п.
Резюме по семинару
Сегодня был дополнительный разбор полета с коллегами, в результате чего были сделаны следующие выводы. Над чем нужно поработать:
1. Я периодически забивал на слайды и рассказывал от себя, иногда забегая вперед, опережая слайды.
2. Не все термины, которые я использовал, были понятны людям. Например, я мог говорить о контекстах синхронизации, подразумевая, что все знакомы с этими понятиями. Поскольку это было не всегда так, часть аудитории терялась.
3. Рассказывать от простого к сложному, а не наоборот. Были случаи, когда я вначале поверхностно касался каких-то тем, а только потом рассматривал их более подробно. Из-за этого у ребят возникали дополнительные вопросы, и появлялось некоторое непонимание.
4. Больше общаться с аудиторией. Я старался задавать вопросы и иногда даже глупо шутить, но стоит вовлекать аудиторию сильнее.
5. Больше рисунков и меньше кода. В общем, на слайдах было много кода, а в дополнительных материалах его было еще больше. Многие понятия, особенно блоки итераторов и, соответственно всю эту асинхронную хрень, нужно визуализировать сильнее. Код не лучшая демонстрация сложного потока исполнения асинхронного кода.
6. Да, задачам (классам Task, Task<,T>, и т.п.) я уделил слишком мало внимания. Нужно больше примеров со всякими ContinueWith и тому подобным, причем лучше в виде рисунков, с явной демонстрацией потока исполнения.
7. В примерах кода не хватало номеров строк, а мне не хватало лазерной указки. Из-за этого иногда приходилось дополнительно бегать по залу и рассказывать кое-что на пальцах.
8. В следующий раз нужно это дело записывать, чтобы посмотреть на себя со стороны и провести более детальный разбор ошибок.
Что понравилось:
Несмотря на то, что есть ряд вопросов, над которыми нужно поработать, семинар, в целом удался. Понравилось то, что мне понравилось вести этот семинар и аудитории понравилось его слушать. Слушатели были отзывчивые и понятливые. Правда в дискуссию вступали только свои, ребята же, которые лично меня не знали, максимум кивали и поднимали руку, на вопросы типа: А вы знаете, кто такой Рихтер?.
В общем, я готов повторить и рассмотреть либо эту тему снова, либо коснуться реактивных расширений, которыми многие ребята заинтересовались.
Вот отсюда можно скачать: (1) презентацию, (2) тестовый проектик.
-----------------------------
(*) Это тонкий намек на Андерса Хейлсберга с компанией, которые собираются добавить фичи для асинхронного программирования в C# и VB.NET,)