At arbejde med serverløse arkitekturer kræver et solidt kendskab til værktøjer som Azure Functions. Denne guide fokuserer på, hvordan man opretter et simpelt Azure Functions-projekt i Visual Studio Code, bygger det, og tester det lokalt, uden brug af en fuld udviklingsmiljø som Visual Studio 2022.
Først og fremmest, når du arbejder med Azure Functions, skal du forstå, at funktionerne kører i en isoleret runtime, hvilket betyder, at de kun er aktiveret, når de bliver kaldt, og de ikke har en kontinuerlig drift. Det gør dem ideelle til microservices og event-drevne applikationer.
Oprettelse af et Projekt i Visual Studio Code
-
Åbn Visual Studio Code og navigér til Chapter14 mappen. Vælg derefter Northwind.AzureFunctions.Service folderen, som du vil bruge til dit projekt.
-
Åbn Command Palette ved at vælge View | Command Palette og skriv "azure f", som vises i figur 14.1. Vælg Azure Functions: Create New Project….
-
Når du bliver bedt om at vælge en mappe til dit projekt, vælg Northwind.AzureFunctions.Service.
-
Vælg de nødvendige indstillinger for dit projekt:
-
Vælg et sprog: C#
-
Vælg .NET runtime: .NET 6.
-
Vælg en skabelon for din første funktion: HTTP trigger.
-
Navngiv funktionen: NumbersToWordsFunction.
-
Namespace: Northwind.AzureFunctions.Service.
-
Autentificeringsniveau: Anonymous.
-
Når du har valgt disse indstillinger, vil Visual Studio Code oprette et Azure Functions-projekt for dig, som er klar til at blive kodet.
Brug af Kommandolinjeværktøjet (CLI)
Hvis du ønsker at arbejde direkte i kommandolinjen, kan du bruge Azure Functions CLI til at oprette og køre projektet.
-
Opret en ny mappe kaldet Chapter14-cli og en undermappe Northwind.AzureFunctions.Service.
-
I kommandoprompten, navigér til Northwind.AzureFunctions.Service mappen og kør følgende kommando for at initialisere dit Azure Functions projekt med C#:
-
For at oprette en ny HTTP-triggeret funktion med anonym adgang, kør:
-
For at starte din funktion lokalt, kan du bruge:
Gennemgang af Azure Functions Projektet
Efter at have oprettet projektet er det vigtigt at forstå de vigtigste komponenter, der udgør et Azure Functions-projekt.
-
Projektfilen indeholder versionen af Azure Functions og de nødvendige pakker for at kunne implementere en funktion, der svarer på HTTP-anmodninger.
-
I host.json filen er logføring til Application Insights aktiveret, men uden at inkludere anmodningstyper.
-
local.settings.json bruges til lokal udvikling, hvor den specifikt indikerer, at projektet skal bruge lokal udviklingslager og et in-process hosting model.
Dette er vigtige filer, som sikrer, at dit projekt fungerer korrekt under lokal udvikling. Hvis du f.eks. oplever problemer med AzureWebJobsStorage i Visual Studio Code, kan du tilføje den nødvendige indstilling og sætte den til UseDevelopmentStorage=true.
Implementering af en Enkel Funktion
Lad os implementere en funktion, der konverterer et tal til ord. Denne funktion tager et tal som input og returnerer det som et ord.
-
Opret en ny klassefil kaldet NumbersToWords.cs.
-
For at spare tid kan du kopiere koden til denne klasse fra følgende GitHub-link:
NumbersToWords.cs - GitHub Repository. -
Hvis du bruger Visual Studio 2022, kan du højreklikke på Function1.cs og omdøbe den til NumbersToWordsFunction.cs.
-
Rediger indholdet i NumbersToWordsFunction.cs for at implementere en funktion, der konverterer et beløb som tal til ord. Eksemplet nedenfor viser, hvordan koden skal se ud:
Test af Funktionen Lokalt
For at teste den funktion, du netop har oprettet, kan du følge disse trin:
-
Start Northwind.AzureFunctions.Service projektet. Hvis du bruger Visual Studio Code, skal du navigere til Run and Debug panelet, vælge Attach to .NET Functions og derefter klikke på Run.
-
Når projektet er startet, vil Azure Functions Core Tools hoste din funktion lokalt på port 7071.
-
Hvis du bliver bedt om at tillade adgang i Windows Firewall, skal du klikke Allow Access.
Når alt er sat op, kan du tilgå funktionen via følgende URL i din browser:
Dette vil returnere tallet 12345 konverteret til ord.
Det er vigtigt at bemærke, at Azure Functions er velegnet til små, uafhængige funktioner, som kan reagerer på begivenheder. Derfor er det væsentligt at planlægge, hvordan du skalerer funktionerne og håndterer forskellige typer af triggers, for at få den bedste ydeevne og sikkerhed.
Hvordan opbygger man en app med .NET MAUI til at håndtere kundeoplysninger?
Når man arbejder med .NET MAUI, er det essentielt at forstå hvordan man korrekt binder data mellem forskellige komponenter og grænseflader. En vigtig del af denne proces involverer oprettelsen af visninger og interaktioner med disse visninger, både for at vise data og opdatere det, når brugeren foretager ændringer. Lad os se på, hvordan du kan implementere funktionalitet for at håndtere kunder i en applikation ved hjælp af .NET MAUI.
I CustomerDetailPage.xaml.cs-modulet ser vi en implementering, hvor der oprettes en visningsmodel, som bruges som bindingkontekst for CustomerDetailPage. Når du arbejder med en sådan side, skal du sikre dig, at konstruktørerne er korrekt sat op, så de håndterer både oprettelse og redigering af kunder. Den første konstruktor i eksemplet modtager et CustomersListViewModel-objekt og initialiserer bindingen til en ny CustomerDetailViewModel. Her ændres sidens titel til "Add Customer", da det er for at tilføje en ny kunde. I den anden konstruktor, hvor både CustomersListViewModel og en CustomerDetailViewModel er til stede, ændres bindingen til den eksisterende kunde, og indsæt-knappen bliver skjult, da det ikke er nødvendigt at tilføje en ny kunde, hvis vi er i redigeringstilstand.
Når brugeren trykker på "Insert"-knappen, tilføjes den nye kunde til CustomersListViewModel, og navigationen tilbage til den forrige side sker asynkront. Denne proces er baseret på den tovejskommunikation, der opstår gennem data binding, som sørger for, at ændringer i brugergrænsefladen automatisk afspejles i datamodellen og vice versa.
Dernæst skal du sikre, at appen kan kommunikere med telefonens indbyggede funktioner, som fx at ringe til en kunde. I dette tilfælde skal du åbne AndroidManifest.xml og tilføje de nødvendige tilladelser for at aktivere telefonopkaldsfunktionaliteten. Når applikationen er startet i Android-emulatoren, kan brugeren navigere til kundelisten, vælge en kunde og opdatere oplysninger som virksomhedsnavn. Dette sker ved hjælp af tovej data binding, så ændringer automatisk synkroniseres mellem brugergrænsefladen og datamodellen.
Testen af appen går videre til at inkludere funktioner som oprettelse af en ny kunde, og brugeren kan interagere med listen af kunder ved at trykke og holde på en post for at få adgang til funktioner som opkald og sletning. Denne interaktivitet gør appen mere dynamisk og brugervenlig.
Endvidere, når du implementerer opkaldsfunktionaliteten, viser appen en prompt, der spørger brugeren, om de vil ringe til den valgte kundes telefonnummer. Ved at bekræfte dette valg åbnes den native telefon-app på enheden, og brugeren kan fortsætte opkaldet derfra. Efter opkaldet vender appen tilbage til sin oprindelige tilstand.
For at afslutte denne funktionalitet kan appen give brugeren mulighed for at opdatere listen af kunder ved at trække ned i listen, hvilket skaber en visuel effekt af opdatering, selvom dataene ikke rent faktisk opdateres, da denne funktion kun er simuleret i emulatoren.
Når det kommer til webtjenester, skal man være opmærksom på, at mobile apps, som f.eks. en iOS-app, kræver sikre forbindelser til webtjenester. Apple’s App Transport Security (ATS) sørger for, at kun sikre forbindelser benyttes. Google har implementeret lignende politikker siden Android 9. For at oprette forbindelse til en webtjeneste, som f.eks. Northwind.Maui.WebApi.Service, der anvender et selvsigneret certifikat, kan der opstå problemer. For at forenkle processen kan man dog deaktivere sikkerhedstjek i appen, selvom dette normalt ikke anbefales i produktion.
Når man arbejder med at oprette en webtjeneste, der håndterer kunder, vil man typisk skabe et minimal API, som kommunikerer med en database som eksempelvis Northwind-databasen. Denne API vil give appen mulighed for at tilføje, opdatere og hente kundeinformationer fra serveren, hvilket gør applikationen mere dynamisk og interaktiv.
Det er vigtigt at forstå, at datahåndtering i .NET MAUI ikke kun involverer interaktionen med brugergrænsefladen, men også at opretholde et effektivt og sikkert datalink til eksterne tjenester og sikre, at appens sikkerhed og ydeevne altid er i fokus. Brug af tovej data binding og korrekt håndtering af eksterne opkald og netværksanmodninger er afgørende for en succesfuld implementering af mobilapplikationer.
Hvordan fungerer Interlocked og asynkron programmering i C#?
Interlocked-operatører er essentielle værktøjer i trådsikker programmering, men de har begrænsninger i forhold til de datatyper, de kan arbejde med. For eksempel fungerer Interlocked ikke på numeriske typer som byte, sbyte, short, ushort og decimal. Til gengæld kan de atomiske operationer Exchange og CompareExchange anvendes på typer som System.Single (float), System.Double (double), nint, nuint samt generiske typer og System.Object. Disse operationer sikrer, at værdier kan udveksles i hukommelsen uden risiko for race conditions, hvilket er afgørende for trådsikkerhed.
Når man i praksis arbejder med flere tråde, er det vigtigt at sikre, at delte ressourcer ikke bliver beskadiget af samtidige ændringer. For eksempel kan en tæller, der sporer antallet af operationer, beskyttes ved at anvende Interlocked.Increment, som atomisk øger en integer-værdi. Det er dog værd at bemærke, at hvis man allerede har en anden låsemekanisme, som en Monitor eller en lås (conch i eksemplet), kan brugen af Interlocked være overflødig, da låsen i sig selv beskytter de delte ressourcer.
Monitor og Interlocked er to simple, men effektive mekanismer til synkronisering, der dog i nogle tilfælde ikke er tilstrækkelige. Når man har behov for mere avanceret synkronisering, kan man overveje andre metoder som ReaderWriterLock og ReaderWriterLockSlim, der tillader flere læsere samtidig, men kun en enkelt skriver ad gangen. Mutex anvendes til at sikre eksklusiv adgang mellem processer, mens Semaphore og SemaphoreSlim begrænser antallet af samtidige tråde, der kan få adgang til en ressource, og dermed fungerer som ressource-throttling. Event wait handles som AutoResetEvent og ManualResetEvent bruges til at synkronisere tråde gennem signalering.
Indførelsen af async og await i C# 5 revolutionerede måden, hvorpå programmer håndterer multitasking, især i brugergrænseflader (GUI) og webapplikationer. Disse nøgleord gør det muligt at skrive asynkrone programmer, der stadig fremstår som sekventielle og letlæselige. Det forbedrer ikke kun responsiviteten, men øger også skalerbarheden, hvilket er vigtigt for moderne applikationer.
I konsolprogrammer var det tidligere ikke muligt at markere Main-metoden som async, hvilket begrænsede brugen af await til kun metoder inde i programmet. Med C# 7.1 blev det muligt at have en asynkron Main, hvilket åbner for mere fleksibel og moderne kodning i konsolapplikationer.
En vigtig nyhed i nyere versioner af .NET er understøttelsen af asynkrone streams, som introduceret i .NET Core 3.0 og C# 8.0. Det muliggør, at metoder kan returnere sekvenser af data asynkront, et stort fremskridt fra tidligere, hvor await kun kunne arbejde med enkeltstående opgaver. Denne funktion er særlig nyttig, når man arbejder med store eller uendelige datasæt, hvor værdier genereres over tid, eksempelvis ved netværkskommunikation eller filbehandling.
I GUI-applikationer er der to grundlæggende regler: langvarige opgaver må ikke køre på UI-tråden, og UI-elementer må kun opdateres på UI-tråden. Før async/await blev introduceret, krævede dette ofte kompleks trådkoordinering for at sikre korrekt og sikker opdatering af brugergrænsefladen. Async og await gør det muligt at skrive kode, som ser ud til at køre synkront, men som under overfladen håndterer disse regler og sikrer en smidig og responsiv brugeroplevelse.
Det er vigtigt at forstå, at effektiv brug af asynkron programmering og korrekt synkronisering ikke blot handler om tekniske detaljer, men om at sikre applikationens stabilitet og ydeevne i virkelige situationer med konkurrence om ressourcer. De rigtige valg af synkroniseringsmekanismer afhænger af konteksten, arten af ressourcerne, og de krav, der stilles til ydeevne og korrekthed. Samtidig bør man være opmærksom på, at asynkron programmering kan introducere nye typer af kompleksitet, især når det gælder fejlhåndtering og debugging.
At mestre disse teknikker kræver både forståelse for deres grundlæggende mekanismer og erfaring med praktiske scenarier, hvor de anvendes. Det gør det muligt at skrive robuste, skalerbare og effektive programmer, som udnytter samtidighedens fulde potentiale uden at gå på kompromis med stabiliteten.
Hvordan de tidlige mennesker brugte værktøjer og ild til at forme deres verden
Hvordan man opdager cyberangreb i cyber-fysiske mikrogrids ved hjælp af maskinlæringsteknikker
Hvordan fortællingens kraft er symptomatisk for viljen til magt over tid og væren

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский