Обучение SynchronizationContext, async и await

Асинхронното програмиране е форма на паралелно програмиране, която ви позволява да изпълнявате задачи отделно от основната нишка на приложението и след това уведомява нишката, когато нейното изпълнение приключи. Asynchrony ви помага да изпълнявате задачи, без необходимост от задържане на потока на изпълнение или отзивчивост на вашето приложение.

Microsoft предостави поддръжка за паралелно програмиране в .Net Framework, за да се възползва от предимствата на многоядрените системи. Можете да използвате асинхронност, за да подобрите производителността и отзивчивостта на вашето приложение.

По същество в приложението има два възможни типа операции. Те включват операции, свързани с изчисления и I / O. Операциите, свързани с изчисления, са тези, при които изчислението може да се извърши на отделна нишка, така че основната нишка да може да продължи с нейното изпълнение. Напротив, операциите, свързани с I / O са тези, при които се изпълняват външно и следователно не е необходимо да блокират текущата нишка, докато I / O е в ход.

Контекст на синхронизация и контекст на изпълнение

Всяка нишка има контекст, свързан с нея - това е известно още като „текущия“ контекст - и тези контексти могат да се споделят между нишките. ExecutionContext съдържа съответни метаданни за текущата среда или контекст, в който се изпълнява програмата. SynchronizationContext представлява абстракция - обозначава местоположението, където се изпълнява кодът на вашето приложение.

SynchronizationContext ви позволява да поставите задача в опашка в друг контекст. Имайте предвид, че всяка нишка може да има свой собствен SynchronizatonContext. Класът SynchronizationContext е добавен наскоро към пространството от имена System.Threading и улеснява комуникацията между нишките. Можете да прочетете повече за SynchronizationContext и ExecutionContext тук.

Дълбоко гмуркане в Async и Await

Трите модела на асинхронно програмиране включват следното:

  1. Модел за асинхронно програмиране (APM)
  2. Базиран на събития асинхронен модел (EAP)
  3. Базиран на асинхронен модел (TAP)

Последният, препоръчителният и също така най-елегантният от всички е TAP.

Имайте предвид, че можете да маркирате метод, използвайки ключовата дума "async", която връща void, Task или Task. Имайте предвид, че когато възникне изключение вътре в асинхронен метод, който има връщащ тип Задача или Задача, подробностите за изключението се съхраняват в екземпляра на Задача.

Напротив, когато възникне изключение вътре в асинхронен метод, който има връщащ тип void, подробностите за изключение се съхраняват в SynchronizationContext, който е бил активен по времето, когато е бил извикан асинхронният метод. По същество не можете да обработвате изключения, създадени в асинхронен метод, който има връщащ тип void, използвайки обработчици на изключения, написани вътре в асинхронния метод. Поради различните изчисления и обработка на грешки в семантиката, препоръчително е да се избягват асинхронни методи с невалидни типове връщане, освен ако няма достатъчна причина да се използват.

Когато използвате ключовата дума "await" в асинхронен метод, методът се разделя в автомат на състоянието. Обърнете внимание, че ключовата дума "await" улавя текущия SynchronizationContext и веднага след като задачата, която е била изчакана с помощта на ключовата дума "await" е завършена, машината на състоянието се възобновява и изпълнението на кода в метода на повикващия се рестартира - това също е известен като продължение. Ако изпълнението на кода, който е бил изчакан с помощта на ключовата дума "await", е завършено по времето, когато се срещне точката на спиране, асинхронният метод (методът, който е маркиран като "асинхронизиран") се изпълнява синхронно. Ако изпълнението на чакания код не е завършено, към чакащия код е приложен продължителен делегат.

Можете да се възползвате от асинхронни методи, които връщат void, за да създадете асинхронни манипулатори на събития. Основният метод не може да бъде маркиран с ключовата дума "async", тъй като това е входната точка на приложението - основният метод "async" ще прекрати момента, в който бъде извикан. Ключовата дума "await" информира компилатора, че методът може да има точка на спиране и възобновяване. Между другото, можете да използвате ключовата дума "await" само за метод, който е маркиран като асинхронен с помощта на ключовата дума "async".

При извикване асинхронен метод се изпълнява синхронно на текущата нишка, независимо от типа на връщане на метода. Когато маркирате метод като асинхронен с помощта на ключовата дума "async", просто информирате компилатора, че методът може да бъде разделен на множество задачи - някои от тези задачи могат да се изпълняват асинхронно. Също така, включването на ключовата дума „async“ в метод не поставя извикването на метода на опашка като част от пула от нишки. Асинхронността (т.е. дали даден метод би имал асинхронно поведение) всъщност зависи от точката на спиране, която сте споменали във вашия метод, използвайки ключовата дума "await". Ако не включите ключовата дума "await" в асинхронен метод, целият метод ще се изпълни синхронно.