Комментарии 6
"Дорогой дедушка Мороз, я ничего не понял в статье Стива Тоуба. Но написал много буков, чтобы ты не сомневался, что я очень сильно старался понять.
На новый год я хочу миллион просмотров и благодарность от читателей."
Функция Impl() возвращает управление на каждом yield return, и поэтому требует многократных вызовов, как если бы она применялась из конструкции на основе foreach.
Вот с этого момента началась какая-то чушь. Нет, функция Impl() требует ровно одного вызова.
Многократные вызовы foreach делает не для функции-генератора, а для метода MoveNext. Это, вообще-то, общеизвестный факт.
Если сравнить с тем что мы имеем для «функций использующих yield return для генерации IEnumerable<> списка» по аналогии с которой мы пытаемся реализовать логику использования async функций, то окажется, что ее нельзя использовать, потому что она требует особенной конструкции с циклом для вызова по месту вызова.
Нет, yield return никогда не требовал особенной конструкции по месту вызова.
Как видите сложность анализа этого решения заключается еще и в том, что надо загрузить и держать в голове реализацию сразу нескольких взаимосвязанных классов, каждый из которых в отдельности вряд ли можно понять вне контекста логики их взаимодействия.
Не нужно.
Пул потоков можно понять без всех остальных классов.
Задачу-Task можно понять зная лишь пул потоков.
Реализацию оператора await можно понять зная лишь Task.
Реализацию асинхронного метода можно понять зная лишь Task и реализацию await.
Реализацию оператора await можно понять зная лишь Task.
Да, понять реализацию на уровне концепции можно. Но реальная реализация там сделана сложнее. И по факту использует подход duck typing, в целом для C# нетипичный.
И это позволяет использовать кое-какие интересные трюки. У меня, например, в одном проекте есть класс, в одном из методов которого есть конструкция await this. Ревнителям чистоты кода сразу сообщу, что это - пет-проект, так что никто посторонний от такого трюка не пострадает.
async await нужно просто понимать как еще один способ работы с функциями возвращающими Task. реально await ждет выполнения Task. Вся "магия" с отзывчивым UI происходит на уровень выше, где-то во фреймворке, где эти Task_и честно обрабатываются по условно классической схеме. async await удобен в "нормальном" коде лишь тем, что это краткий способ запустить серию последовательных асинхронных задач и лишь "наверху" можно получить реальную асинхронность. К счастью, наверху все сделано.
После прочтения статьи у меня сложилось впечатление, что простой, но точный перевод статьи Тауба лучше бы способствовал пониманию async/await, чем данная статья. Бльно уж много в ней мыслей о том, как это всё сложно, которые IMHO только задерживают читателя.
Но, возможно, это мое впечатление обусловлено тем, что я давно знаю, как реализован async/await.
Async/Await из C#. Головоломка для разработчиков компилятора и для нас