Programmering

Hvordan bruke ValueTask i C #

Asynkron programmering har vært i bruk i ganske lang tid nå. De siste årene har det blitt kraftigere med introduksjonen av asynkroniserte og avvente nøkkelord. Du kan dra nytte av asynkron programmering for å øke applikasjonens respons og gjennomstrømning.

Den anbefalte returtypen for en asynkron metode i C # er Oppgave. Du bør returnere Task hvis du vil skrive en asynkron metode som returnerer en verdi. Hvis du ønsker å skrive en hendelsesbehandler, kan du returnere ugyldig i stedet. Inntil C # 7.0 kan en asynkron metode returnere Oppgave, Oppgave eller ugyldig. Fra og med C # 7.0 kan en asynkron metode også returnere ValueTask (tilgjengelig som en del av System.Threading.Tasks.Extensions-pakken) eller ValueTask. Denne artikkelen presenterer en diskusjon om hvordan vi kan jobbe med ValueTask i C #.

For å jobbe med kodeeksemplene som er gitt i denne artikkelen, bør du ha Visual Studio 2019 installert på systemet ditt. Hvis du ikke allerede har en kopi, kan du laste ned Visual Studio 2019 her.

Opprett et .NET Core-konsollapplikasjonsprosjekt i Visual Studio

La oss først lage et .NET Core-konsollapplikasjonsprosjekt i Visual Studio. Forutsatt at Visual Studio 2019 er installert i systemet ditt, følger du trinnene som er beskrevet nedenfor for å opprette et nytt .NET Core-konsollapplikasjonsprosjekt i Visual Studio.

  1. Start Visual Studio IDE.
  2. Klikk på "Opprett nytt prosjekt."
  3. I vinduet "Opprett nytt prosjekt" velger du "Konsollapp (.NET Core)" fra listen over maler som vises.
  4. Klikk på Neste.
  5. I vinduet “Konfigurer ditt nye prosjekt” som vises, angir du navnet og stedet for det nye prosjektet.
  6. Klikk på Opprett.

Dette vil opprette et nytt .NET Core-konsollapplikasjonsprosjekt i Visual Studio 2019. Vi bruker dette prosjektet til å illustrere bruken av ValueTask i de påfølgende delene av denne artikkelen.

Hvorfor skal jeg bruke ValueTask?

En oppgave representerer tilstanden til en eller annen operasjon, dvs. om operasjonen er fullført, kansellert og så videre. En asynkron metode kan returnere enten en oppgave eller en oppgave.

Nå, siden Task er en referansetype, innebærer å returnere et Task-objekt fra en asynkron metode å tildele objektet på den administrerte bunken hver gang metoden kalles. Dermed er en advarsel ved bruk av Task at du må tildele minne i den administrerte haugen hver gang du returnerer et Task-objekt fra metoden din. Hvis resultatet av operasjonen som utføres etter din metode er tilgjengelig umiddelbart eller fullføres synkront, er ikke denne tildelingen nødvendig og blir derfor kostbar.

Her er nøyaktig hvor ValueTask kommer til unnsetning. ValueTask gir to store fordeler. For det første forbedrer ValueTask ytelsen fordi den ikke trenger haugetildeling, og for det andre er den både enkel og fleksibel å implementere. Ved å returnere ValueTask i stedet for Task fra en asynkron metode når resultatet er umiddelbart tilgjengelig, kan du unngå unødvendig overhead av allokering siden "T" her representerer en struktur og en struct i C # er en verditype (i motsetning til "T" i Oppgave, som representerer en klasse).

Oppgave og verdi Oppgave representerer to primære "ventelige" typer i C #. Merk at du ikke kan blokkere på en ValueTask. Hvis du trenger å blokkere, bør du konvertere ValueTask til en oppgave ved hjelp av AsTask-metoden og deretter blokkere det referanseoppgaveobjektet.

Vær også oppmerksom på at hver ValueTask bare kan konsumeres en gang. Her innebærer ordet "forbruker" at en ValueTask kan asynkront vente på (venter) på at operasjonen skal fullføres eller dra nytte av AsTask for å konvertere en ValueTask til en Task. Imidlertid bør en ValueTask forbrukes bare en gang, hvoretter ValueTask bør ignoreres.

ValueTask-eksempel i C #

Anta at du har en asynkron metode som returnerer en oppgave. Du kan dra nytte av Task.FromResult for å opprette Task-objektet som vist i kodebiten gitt nedenfor.

offentlig oppgave GetCustomerIdAsync ()

{

returner Task.FromResult (1);

}

Ovennevnte kodebit oppretter ikke hele maskinens magi for asynk, men den tildeler et oppgaveobjekt i den administrerte bunken. For å unngå denne tildelingen, vil du kanskje dra nytte av en ValueTask i stedet som vist i kodebiten gitt nedenfor.

offentlig ValueTask GetCustomerIdAsync ()

{

returner ny ValueTask (1);

}

Følgende kodebit illustrerer en synkron implementering av ValueTask.

 offentlig grensesnitt IRepository

    {

ValueTask GetData ();

    }

Repository-klassen utvider IR-depotgrensesnittet og implementerer metodene som vist nedenfor.

  public class Repository: IRepository

    {

offentlig ValueTask GetData ()

        {

var verdi = standard (T);

returner ny ValueTask (verdi);

        }

    }

Slik kan du ringe GetData-metoden fra Main-metoden.

statisk tomrom Main (streng [] args)

        {

IR-depot = nytt arkiv ();

var resultat = repository.GetData ();

hvis (resultat.IsFullført)

Console.WriteLine ("Operasjonen fullført ...");

ellers

Console.WriteLine ("Operasjonen er ufullstendig ...");

Console.ReadKey ();

        }

La oss nå legge til en annen metode i depotet vårt, denne gangen en asynkron metode som heter GetDataAsync. Her er hvordan det modifiserte IRepository-grensesnittet vil se ut.

offentlig grensesnitt IRepository

    {

ValueTask GetData ();

ValueTask GetDataAsync ();

    }

GetDataAsync-metoden er implementert av Repository-klassen som vist i kodebiten gitt nedenfor.

  public class Repository: IRepository

    {

offentlig ValueTask GetData ()

        {

var verdi = standard (T);

returner ny ValueTask (verdi);

        }

offentlig asynkronisering ValueTask GetDataAsync ()

        {

var verdi = standard (T);

venter på Task.Delay (100);

returverdi;

        }

    }

Når skal jeg bruke ValueTask i C #?

Selv om fordelene ValueTask gir, er det visse avveininger med å bruke ValueTask i stedet for Task. ValueTask er en verditype med to felt, mens Task er en referansetype med et enkelt felt. Derfor betyr bruk av en ValueTask å jobbe med flere data siden en metodeanrop ville returnere to datafelt i stedet for ett. Også, hvis du venter på en metode som returnerer en ValueTask, vil tilstandsmaskinen for den asynkrone metoden også være større - fordi den må imøtekomme en struktur som inneholder to felt i stedet for en enkelt referanse i tilfelle en oppgave.

Videre, hvis forbrukeren av en asynkron metode bruker Task.WhenAll eller Task.WhenAny, kan det være kostbart å bruke ValueTask som returtype i en asynkron metode. Dette er fordi du trenger å konvertere ValueTask til Task ved hjelp av AsTask-metoden, noe som vil medføre en tildeling som lett kunne unngås hvis en bufret Task i utgangspunktet hadde blitt brukt.

Her er tommelfingerregelen. Bruk Oppgave når du har et stykke kode som alltid vil være asynkron, dvs. når operasjonen ikke blir fullført umiddelbart. Dra nytte av ValueTask når resultatet av en asynkron operasjon allerede er tilgjengelig, eller når du allerede har et hurtigbufret resultat. Uansett bør du utføre den nødvendige ytelsesanalysen før du vurderer ValueTask.

Hvordan gjøre mer i C #:

  • Hvordan bruke uforanderlighet i C
  • Slik bruker du const, readonly og static i C #
  • Slik bruker du datanoteringer i C #
  • Hvordan jobbe med GUIDer i C # 8
  • Når skal jeg bruke en abstrakt klasse vs. grensesnitt i C #
  • Hvordan jobbe med AutoMapper i C #
  • Hvordan bruke lambdauttrykk i C #
  • Hvordan jobbe med Action-, Func- og Predicate-delegater i C #
  • Hvordan jobbe med delegater i C #
  • Slik implementerer du en enkel logger i C #
  • Hvordan jobbe med attributter i C #
  • Hvordan jobbe med log4net i C #
  • Slik implementerer du mønsteret for depotdesign i C #
  • Hvordan jobbe med refleksjon i C #
  • Hvordan jobbe med filsystemwatcher i C #
  • Hvordan utføre lat initialisering i C #
  • Hvordan jobbe med MSMQ i C #
  • Hvordan jobbe med utvidelsesmetoder i C #
  • Hvordan vi lambdauttrykk i C #
  • Når skal du bruke det flyktige nøkkelordet i C #
  • Slik bruker du avkastningsnøkkelordet i C #
  • Hvordan implementere polymorfisme i C #
  • Hvordan lage din egen oppgaveplanlegger i C #
  • Hvordan jobbe med RabbitMQ i C #
  • Hvordan jobbe med en tuple i C #
  • Utforske virtuelle og abstrakte metoder i C #
  • Hvordan bruke Dapper ORM i C #
  • Hvordan bruke flyvevekt mønster i C #
$config[zx-auto] not found$config[zx-overlay] not found