[Киев] Семинар по асинхронному программированию в .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;)
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 2

      +1
      Спасибо за презентацию и за самплы.

      >Больше рисунков и меньше кода. В общем, на слайдах было много кода, а в дополнительных материалах его было еще больше.

      Скажу только за себя. Много кода в презентации не айс — утомляет. А вот в дополнительных материалах мне нравится, т.к. помогает понять некоторые вещи из матчасти, которые сразу не усвоились, например.
        0
        PowerThreading, Async/Await, TPL DataFlow… проза жизни. Знаете что действительно стимулирует? Такие разработки как LMAX Disruptor. Вот это действительно “айс”, ребята могут выжать 100k TPS и latency < 1ms (!!!) с обычного железа. Тем, кого интересует высокая производительность очень рекомендую. Кстати, у Disruptor’а есть даже порт на .Net, хотя на сколько я знаю, он еще не дотягивает до реализации на Java (странно, ведь у нас есть System.ValueType).

        И еще — это мне одному кажется что иметь метод, который возвращает int но в сигнатуре у него Task<int> — это как-то неправильно? Выглядит реальной поломкой шаблона модели.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое