Learning SynchronizationContext, async och vänta

Asynkron programmering är en form av parallell programmering som gör att du kan utföra uppgifter som är separata från huvudapplikationstråden och sedan meddelar tråden när dess körning är över. Asynkroni hjälper dig att utföra uppgifter utan behov av att hålla upp körningsflödet eller responsen i din applikation.

Microsoft har tillhandahållit stöd för parallell programmering i .Net Framework för att dra nytta av fördelarna med flerkärniga system. Du kan utnyttja asynkroni för att förbättra din applikations prestanda och respons.

I huvudsak finns det två möjliga typer av operationer i en applikation. Dessa inkluderar datorbundna och I / O-bundna operationer. Beräkningsbundna operationer är de där beräkningen kan utföras på en separat tråd så att huvudtråden kan fortsätta med sin körning. Tvärtom är I / O-bundna operationer de som utförs externt och därför behöver de inte blockera den aktuella tråden medan I / O pågår.

Synkroniseringskontext och körningskontext

Varje tråd har ett sammanhang associerat - det kallas också det "aktuella" sammanhanget - och dessa sammanhang kan delas över trådar. ExecutionContext innehåller relevanta metadata för den aktuella miljön eller det sammanhang där programmet körs. SynchronizationContext representerar en abstraktion - den anger platsen där programmets kod körs.

En SynchronizationContext gör att du kan köa en uppgift i ett annat sammanhang. Observera att varje tråd kan ha sin egen SynchronizatonContext. SynchronizationContext-klassen har nyligen lagts till i System.Threading-namnområdet och underlättar kommunikation mellan trådar. Du kan läsa mer om SynchronizationContext och ExecutionContext här.

Ett djupt dyk inuti Async och Await

De tre asynkrona programmeringsmönstren inkluderar följande:

  1. Asynkron programmeringsmodell (APM)
  2. Händelsebaserat asynkront mönster (EAP)
  3. Task-based Asynchronous Pattern (TAP)

Det senaste, det rekommenderade och även det mest eleganta av allt detta är TAP.

Observera att du kan markera en metod med hjälp av nyckelordet "async" som returnerar ogiltig, Task eller Task. Observera att när ett undantag förekommer i en asynkron metod som har en typ av uppgift eller uppgift returneras undantagsuppgifterna i uppgiftsinstansen.

Tvärtom, när ett undantag förekommer i en asynkron metod som har en returtyp av tomrum, lagras undantagsuppgifterna i SynchronizationContext som var aktiv vid den tidpunkt då den asynkrona metoden anropades. I grund och botten kan du inte hantera undantag som tagits upp inom en asynkron metod med en returtyp av tomrum med hjälp av undantagshanterare skrivna i den asynkrona metoden. På grund av de olika databehandlings- och felhanteringssemantikerna är det tillrådligt att undvika asynkrona metoder med ogiltiga returtyper om det inte finns tillräcklig anledning att använda dem.

När du använder nyckelordet "vänta" i en asynkron metod delas metoden in i en tillståndsmaskin. Observera att nyckelordet "vänta" fångar den aktuella SynchronizationContext och så snart uppgiften som har väntats med hjälp av "vänta" nyckelordet är klar, återupptas tillståndsmaskinen och körningen av koden i uppringningsmetoden startas om - detta känd som fortsättning. Om körning av koden som har väntats med nyckelordet "vänta" har slutförts vid den tidpunkt då upphängningspunkten påträffas, körs den asynkrona metoden (metoden som har markerats som "asynk") synkront. Om exekveringen av den väntade koden inte är fullständig bifogas en fortsättningsdelegat till den väntade koden.

Du kan dra nytta av asynkrona metoder som returnerar ogiltiga för att skapa asynkrona händelsehanterare. Huvudmetoden kan inte markeras med nyckelordet "async" eftersom det är programmets ingångspunkt - en "async" Main-metod skulle avslutas när det kallas. Nyckelordet "vänta" informerar kompilatorn om att metoden kan ha en avstängnings- och återupptagningspunkt. För övrigt kan du bara använda nyckelordet "vänta" på en metod som har markerats som asynkron med "async" -nyckelordet.

En async-metod när den anropas körs synkront på den aktuella tråden oavsett metodens returtyp. När du markerar en metod som asynkron med nyckelordet "async", informerar du bara kompilatorn om att metoden kan delas upp i flera uppgifter - vissa av dessa uppgifter kan utföras asynkront. Införandet av nyckelordet "async" i en metod köar inte metodinropet som en del av trådpoolen. Asynkronin (dvs huruvida en metod skulle ha asynkront beteende) beror faktiskt på den upphängningspunkt du har nämnt i din metod med hjälp av nyckelordet "vänta". Om du inte inkluderar sökordet "vänta" i en asynkron metod, skulle hela metoden köras synkront.