1 August

Как я понимаю асинхронный код?

.NET
Sandbox
Привет, Хабр! Представляю вашему вниманию перевод (с небольшими корректировками) статьи «How Do I Think About Async Code?!» автора Leslie Richardson.

Асинхронный код становится все более популярным для написания отзывчивых приложений. К сожалению, асинхронное программирование так же привносит дополнительные трудности. Как следствие, понять, как работает такой код, может быть непростой задачей, вне зависимости от вашего опыта. Если вы только начали работать с асинхронным кодом, или вы захотели освежить свое понимание – это введение в мир асинхронного программирования!

Что такое асинхронный код?


Асинхронное программирование позволяет вам выполнить блок кода без остановки (или блокировки) всего потока, в котором выполняется действие. Распространенный миф об асинхронном коде заключается в том, что он улучшает производительность, что не всегда верно. Вместо этого главная особенность асинхронного программирования заключается в том, что оно увеличивает количество задач (пропускную способность), которые могут выполняться одновременно, без необходимости блокировать поток, в котором эти действия выполняются.

Вам может показаться, что асинхронный код очень похож на многопоточный, ведь, в конце концов, множество методов может выполняться одновременно в обоих случаях. В действительности, асинхронное программирование может использоваться вместе как с однопоточными, так и с многопоточными приложениями. Это значит, что у вас может быть однопоточная асинхронная программа, в которой один поток может запускать параллельные задачи. И наоборот, у вас также может быть многопоточное асинхронное приложение, в котором несколько потоков могут запускать несколько параллельных задач.

Почему мне стоит использовать асинхронный код? Пример, пожалуйста!


Чтобы иметь какую-то аналогию для демонстрации асинхронного программирования, рассмотрим процесс выпечки пирога. Этот процесс будет представлен потоком, который выполняет несколько шагов (или задач), как показано в коде ниже. Этот код корректен, и у вас все равно получится вкусный пирог после выполнения метода. Однако, поскольку весь код является синхронным, каждая строка будет выполняться последовательно. Другими словами, вы будете стоять совершенно неподвижно, ожидая, пока печь завершит предварительный нагрев. А ведь в это же самое время вы могли бы сделать тесто для вашего пирога!

Синхронный метод MakeCake()

image

Синхронная программа выпекания пирога

image

В реальной жизни вы, как правило, разделяете этот процесс на задачи, замешиваете тесто, пока духовка разогревается. Или делаете глазурь, в то время как пирог запекается в духовке. Это увеличивает вашу производительность и позволяет испечь торт намного быстрее. Это как раз тот случай, где асинхронный код пригодится! Сделав наш текущий код асинхронным, мы сможем заняться другими делами, чтобы скоротать время, в то время пока мы ожидаем(await) результата задачи(task), такой как выпекание пирога в духовке.
Чтобы сделать это – изменим наш код, а так же добавим метод PassTheTime. Теперь наш код сохраняет состояние задачи, запускает другую синхронную или асинхронную операцию и получает результат сохраненной задачи, в тот момент, когда это необходимо.

Асинхронный метод MakeCake()
image

Асинхронная программа выпечки пирога
image

По сравнению с синхронным методом MakeCake, в котором отсутствует метод PassTheTime, асинхронному методу MakeCakeAsync удается выполнить больше задач, не блокируя поток, что сокращает время, необходимое для выполнения всего метода в целом.

Сравнение асинхронной и синхронной программ

image

Как мне писать асинхронный код в .NET?


C # позволяет писать асинхронный код, используя тип Task и ключевые слова await и async. Тип Task сообщает вызывающей стороне о возможном типе возвращаемого значения. Он также указывает на то, что другие действия могут продолжать выполняться в вызвавшем его методе. Ключевое слово async работает в паре с ключевым словом await, которое уведомляет компилятор о том, что нам потребуется возвращаемое методом значение, но не сразу. В результате нам не нужно блокировать вызывающий поток, и мы можем продолжать выполнение других задач, пока не потребуется ожидаемое значение. Первоначально асинхронный метод будет выполняться синхронно, пока не будет найдено ключевое слово await. Это именно тот момент, когда выполнение метода начнется асинхронно.

Я узнал об асинхронном коде! Что теперь?


Хотя асинхронное приложение выпечки пирога это прекрасно, но есть много других реальных приложений, которые также используют асинхронный код. Два наиболее распространенных примера:

Приложения, использующие HTTP-запросы — в зависимости от запроса, обработка HTTP-вызовов может занять длительное время. Использование асинхронного кода позволяет нам выполнить другие операции, пока мы ожидаем ответа от сервера.

Пример запроса HTTP GET

image

Приложения, с пользовательским интерфейсом — приложения WPF или любые другие, использующие кнопки, текстовые поля и другие ресурсы UX, также отлично подходят для асинхронной реализации. Например, приложение WPF, производящее анализ файла. Данная процедура может занять некоторое время. Однако, сделав это действие асинхронным, вы по-прежнему сможете взаимодействовать с пользовательским интерфейсом, не останавливая приложение полностью, во время ожидания завершения операции.
Tags:c#.netasync/await
Hubs: .NET
-4
5k 22
Comments 8