Kako koristiti ValueTask u C #

Asinhrono programiranje koristi se već duže vrijeme. Posljednjih godina učinio ga je snažnijim uvođenjem ključnih riječi async i await. Možete iskoristiti asinkrono programiranje kako biste povećali odziv i propusnost vaše aplikacije.

Preporučena vrsta povrata asinkrone metode u C # je Zadatak. Trebali biste vratiti Task ako želite napisati asinkronu metodu koja vraća vrijednost. Ako želite napisati voditelj događaja, umjesto toga možete se vratiti praznim. Do C # 7.0 asinkrona metoda može vraćati zadatak, zadatak ili void. Počevši od C # 7.0, asinkrona metoda također može vratiti ValueTask (dostupan kao dio paketa System.Threading.Tasks.Extensions) ili ValueTask. Ovaj članak predstavlja raspravu o tome kako možemo raditi s ValueTask u C #.

Da biste radili s primjerima koda iz ovog članka, u sustavu biste trebali instalirati Visual Studio 2019. Ako još nemate kopiju, ovdje možete preuzeti Visual Studio 2019.

Stvorite projekt aplikacije konzole .NET Core u Visual Studiju

Prvo, kreirajmo projekt aplikacije .NET Core konzole u Visual Studiju. Pod pretpostavkom da je Visual Studio 2019 instaliran u vašem sustavu, slijedite korake opisane u nastavku da biste u Visual Studiju stvorili novi projektni program konzole .NET Core.

  1. Pokrenite Visual Studio IDE.
  2. Kliknite "Stvori novi projekt".
  3. U prozoru "Stvori novi projekt" s popisa predložaka odaberite "Aplikacija konzole (.NET Core)".
  4. Kliknite Dalje.
  5. U sljedećem prozoru "Konfiguriranje novog projekta" navedite naziv i mjesto za novi projekt.
  6. Kliknite Stvori.

To će stvoriti novi projektni program konzole .NET Core u Visual Studiju 2019. Ovaj ćemo projekt koristiti za ilustraciju upotrebe ValueTaska u sljedećim odjeljcima ovog članka.

Zašto bih trebao koristiti ValueTask?

Zadatak predstavlja stanje neke operacije, tj. Je li operacija dovršena, otkazana itd. Asinhrona metoda može vratiti zadatak ili vrijednost zadataka.

Sada, budući da je Task referentni tip, vraćanje objekta Task iz asinkrone metode podrazumijeva dodjelu objekta na upravljanoj hrpi svaki put kada se metoda pozove. Dakle, jedno upozorenje u korištenju Zadataka jest da morate dodijeliti memoriju u upravljanoj hrpi svaki put kada vratite objekt Zadatak iz svoje metode. Ako je rezultat operacije koju izvodi vaša metoda dostupan odmah ili se završi sinkronizirano, ovo dodjeljivanje nije potrebno i stoga postaje skupo.

Ovdje točno dolazi u pomoć ValueTask. ValueTask pruža dvije glavne prednosti. Prvo, ValueTask poboljšava performanse jer mu nije potrebna raspodjela hrpe, a drugo, jednostavan je i fleksibilan za implementaciju. Vraćanjem ValueTask umjesto Task iz asinkrone metode kada je rezultat odmah dostupan, možete izbjeći nepotrebne režijske izdvajanja jer "T" ovdje predstavlja strukturu, a struct u C # je vrsta vrijednosti (za razliku od "T" u Zadatak, koji predstavlja razred).

Task i ValueTask predstavljaju dvije primarne vrste "čekanja" u C #. Imajte na umu da ne možete blokirati ValueTask. Ako trebate blokirati, pretvorite ValueTask u zadatak pomoću metode AsTask, a zatim blokirajte taj referentni objekt Zadatak.

Također imajte na umu da se svaka ValueTask može potrošiti samo jednom. Ovdje riječ "trošiti" implicira da ValueTask može asinkrono čekati (pričekati) da se operacija dovrši ili iskoristiti AsTask za pretvaranje ValueTask u zadatak. Međutim, ValueTask treba potrošiti samo jednom, nakon čega ValueTask treba zanemariti.

Primjer ValueTask u C #

Pretpostavimo da imate asinkronu metodu koja vraća zadatak. Možete iskoristiti Task.FromResult za stvaranje objekta Task kao što je prikazano u isječku koda koji je dat u nastavku.

javni zadatak GetCustomerIdAsync ()

{

    povratak Task.FromResult (1);

}

Gornji isječak koda ne stvara cjelokupnu magiju asinkronog strojnog stroja, ali dodjeljuje objekt Zadatak u upravljanoj hrpi. Da biste izbjegli ovu dodjelu, umjesto toga biste trebali iskoristiti ValueTask, kao što je prikazano u isječku koda koji je dat u nastavku.

javna ValueTask GetCustomerIdAsync ()

{

    vrati novu ValueTask (1);

}

Sljedeći isječak koda ilustrira sinkronu implementaciju ValueTask.

 javno sučelje IRepository

    {

        ValueTask GetData ();

    }

Klasa Repozitorij proširuje sučelje IRepository i implementira njegove metode kako je prikazano u nastavku.

    spremište javne klase: IRepository

    {

        javna ValueTask GetData ()

        {

            var vrijednost = zadana (T);

            vrati novu ValueTask (vrijednost);

        }

    }

Evo kako možete pozvati metodu GetData iz glavne metode.

statička praznina Main (string [] args)

        {

            Repozitorij IRepository = novo Repozitorij ();

            var rezultat = spremište.GetData ();

            if (rezultat.IsCompleted)

                 Console.WriteLine ("Operacija dovršena ...");

            drugo

                Console.WriteLine ("Operacija nije dovršena ...");

            Console.ReadKey ();

        }

Dodajmo sada još jednu metodu u naše spremište, ovaj put asinkronu metodu nazvanu GetDataAsync. Evo kako bi izgledalo modificirano sučelje IRepository.

javno sučelje IRepository

    {

        ValueTask GetData ();

        ValueTask GetDataAsync ();

    }

Metodu GetDataAsync implementira klasa Repozitorij kao što je prikazano u isječku koda koji je dan u nastavku.

    spremište javne klase: IRepository

    {

        javna ValueTask GetData ()

        {

            var vrijednost = zadana (T);

            vrati novu ValueTask (vrijednost);

        }

        javna async ValueTask GetDataAsync ()

        {

            var vrijednost = zadana (T);

            čekaju Task.Delay (100);

            povratna vrijednost;

        }

    }

Kada trebam koristiti ValueTask u C #?

Iako blagodati koje ValueTask pruža, postoje određeni kompromisi za korištenje ValueTaska umjesto Taska. ValueTask je vrsta vrijednosti s dva polja, dok je Zadatak referentna vrsta s jednim poljem. Stoga upotreba ValueTask znači rad s više podataka jer bi poziv metode vratio dva polja podataka umjesto jednog. Također, ako čekate metodu koja vraća ValueTask, državni stroj za tu asinkronu metodu također bi bio veći - jer bi u slučaju zadatka morao primiti strukturu koja sadrži dva polja umjesto jedne reference.

Nadalje, ako potrošač asinkrone metode koristi Task.WhenAll ili Task.WhenAny, upotreba ValueTask kao tipa povrata u asinkronoj metodi može postati skupa. To je zato što biste ValueTask trebali pretvoriti u zadatak koristeći metodu AsTask, što bi rezultiralo raspodjelom koju je lako moguće izbjeći da je uopće korišten predmemorirani zadatak.

Ovdje je pravilo palca. Koristite Task kad imate dio koda koji će uvijek biti asinkron, tj. Kada operacija neće odmah završiti. Iskoristite ValueTask kada je rezultat asinkrone operacije već dostupan ili kada već imate predmemorirani rezultat. U svakom slučaju, trebali biste izvršiti potrebnu analizu izvedbe prije razmatranja ValueTaska.

Kako učiniti više u C #:

  • Kako se koristi nepromjenjivost u C
  • Kako koristiti const, readonly i static u C #
  • Kako koristiti bilješke podataka u C #
  • Kako raditi s GUID-ovima u C # 8
  • Kada koristiti apstraktnu klasu naspram sučelja u C #
  • Kako raditi s AutoMapperom u C #
  • Kako koristiti lambda izraze u C #
  • Kako raditi s delegatima Action, Func i Predicate u C #
  • Kako raditi s delegatima u C #
  • Kako implementirati jednostavni zapisnik u C #
  • Kako raditi s atributima u C #
  • Kako raditi s log4netom na C #
  • Kako implementirati obrazac dizajna spremišta u C #
  • Kako raditi s refleksijom u C #
  • Kako raditi s nadzornikom datoteka u C #
  • Kako izvesti lijenu inicijalizaciju u C #
  • Kako raditi s MSMQ-om u C #
  • Kako raditi s metodama produženja u C #
  • Kako do nas lambda izrazi u C #
  • Kada upotrijebiti hlapljivu ključnu riječ u C #
  • Kako koristiti ključnu riječ yield u C #
  • Kako implementirati polimorfizam u C #
  • Kako izraditi vlastiti planer zadataka u C #
  • Kako raditi s RabbitMQ u C #
  • Kako raditi s korpicom u C #
  • Istraživanje virtualnih i apstraktnih metoda u C #
  • Kako koristiti Dapper ORM u C #
  • Kako koristiti uzorak dizajna muhe u C #