Правилно ли разбирам работата и ползите на async/await?

+4 гласа
72 прегледа
попитан 2016 март 29 в .NET от Nikoleta.V. (4,090 точки)

Няколко пъти съм спорил относно async/await дали разбиранията ми за тях са правилни. Наистина ще съм благодарен ако някой потвърди или опровергае разбиранията ми и да изясни неясностите,за да не разпространявам грешна информация.

Работа на високо ниво

Async/await е начин за избягване на бъркотиите с връщане на резултат от функции при писане на асинхронен код. Нишка,която изпълнява асинхронен метод ще се върне към thread pool-а, когато попадне на await и ще продължи, когато изчакваната операция приключи

Работа на ниско ниво

JIT ще раздели асинхронните методи на отделни части около await, позволявайки да се влезе отново в метода като състоянието му се запази. Отдолу това включва някакъв вид машина на състоянието.

Отношение към конкурентността

Async/await не предполага конкурентност. Приложение, написано с тях може да бъде изцяло еднонишково, докато все пак използва всички плюсове, както и node.js прави с callback-ите.За разлика от node.js, .NET е многонишков и използвайки async/await, получавате плюсовете от това да не блокирате входа/изхода без да ползвате callback-и докато се изпълняват много нишки.

Ползи

Async/await освобождава нишките да вършат друга работа докато се чака входа/изхода да приключи. Може да се съчетава с TPL да върши работа,обвързана с процесора на много нишк или извън нишката на графичния интерфейс.

За да се извлекат ползите от не блокирането на входа/изхода, асинхронните методи трябва да се изградят върху API-та, които наистина се възползват от това, които са предоставени от операционната система.

Неправилно използване

Тук разбирането ми е най-спорно. Доста хора вярват, че слагайки блокираща операция в Task и ползвайки async/await ще подобрят производителността. Създаването на допълнителна нишка да извърши операцията, връщането на  оригиналната нишка в thread pool-а и чак тогава продължаването на оригиналния метод след като се свърши задачата, са все ненужни промени, които всъщност не освобождават нишките да вършат друга работа. Докато това е повече неправилно ползване на TPL,а не на async/await, грешното мислене се корени в неправилното разбиране на async/await.

1 отговор

0 гласа
отговорени 2016 март 30 от valeri.hristov (7,340 точки)

Общо взето е вярно

Все пак,имам няколко забележки:

  • Нишката,която започва изпълнението на асинхронен метод е нишката на този,който я извиква. Това значи, че може и да е,може и да не е нишка от Thread pool-a
  • Ако се стигне await, но това, което трябва да се await-не вече е готово, нишката продължава изпълнението на метода синхронно.
  • Нишката,която продължава изпълнението на метода е обикновено нишка от thread pool-а, но това зависи от SyncrhonizationContext и TaskScheduler.
  • JIT тук не се намесва(поне не повече от обикновено). Компилаторът е този,който връща асинхронния метод в машината на състоянието.
  • Вярно е, че async-await не задължително предполага конкурентност, тъй като може да е еднонишково. Все пак може да бъде конкурентно дори ако една нишка започва и изчаква множество асинхронни операции едновременно.
  • Async-await и TPL не са напълно отделни. Async/await се гради върху TPL. Затова се нарича Task-based Asynchronous Pattern.
  • Почти всички асинхронни операции са входно-изходни, но все пак не всички. Можеш да забавиш асинхронно с Task.Delay или чрез синхронизатори като SemaphoreSlim.WaitAsync.
...