четверг, 7 июля 2011 г.

Семинар по асинхронному программированию в .Net

Вчера я был на первом семинаре вообще и по .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;)

7 комментариев:

  1. Если будет возможность, запишите видео доклада - с удовольствием бы посмотрел!

    ОтветитьУдалить
  2. Я собираюсь повторить доклад на следующей встрече Kiev ALT.NET, думаю, что там есть шансы его записать.
    Если же вы из Киева, то есть шансы его и самому увидеть;)

    ОтветитьУдалить
  3. Да блин, прямо в Киев захотелось :). А в московском офисе люксофта выступать не будешь?

    ОтветитьУдалить
  4. @eugene: ну, будут желающие, думаю, что это возможно. Как минимум - вебинар. Ну, а если желающих в Московском офисе будет достаточно, то, думаю, что реально и в Москву прокатиться:)

    ОтветитьУдалить
  5. Здорово. Если что-то получится - может рассылочку тогда сделаешь - что, где, когда?

    ОтветитьУдалить
  6. А когда встеча Kiev ALT.NET ?

    ОтветитьУдалить
  7. @eugene: да, если что-то даже намечаться будет, то я обязательно напишу. А уж, если получится, то и подавно!

    @Taras: встреча намечена на конец сентября.

    ОтветитьУдалить