Вчера я был на первом семинаре вообще и по .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;)
Если будет возможность, запишите видео доклада - с удовольствием бы посмотрел!
ОтветитьУдалитьЯ собираюсь повторить доклад на следующей встрече Kiev ALT.NET, думаю, что там есть шансы его записать.
ОтветитьУдалитьЕсли же вы из Киева, то есть шансы его и самому увидеть;)
Да блин, прямо в Киев захотелось :). А в московском офисе люксофта выступать не будешь?
ОтветитьУдалить@eugene: ну, будут желающие, думаю, что это возможно. Как минимум - вебинар. Ну, а если желающих в Московском офисе будет достаточно, то, думаю, что реально и в Москву прокатиться:)
ОтветитьУдалитьЗдорово. Если что-то получится - может рассылочку тогда сделаешь - что, где, когда?
ОтветитьУдалитьА когда встеча Kiev ALT.NET ?
ОтветитьУдалить@eugene: да, если что-то даже намечаться будет, то я обязательно напишу. А уж, если получится, то и подавно!
ОтветитьУдалить@Taras: встреча намечена на конец сентября.