Programovanie

Ako používať ValueTask v C #

Asynchrónne programovanie sa používa už dosť dlho. V posledných rokoch bola vylepšená zavedením asynchrónneho kódu a čaká na kľúčové slová. Asynchrónne programovanie môžete využiť na zvýšenie odozvy a priepustnosti svojej aplikácie.

Odporúčaný návratový typ asynchrónnej metódy v C # je Task. Úlohu by ste mali vrátiť, ak chcete napísať asynchrónnu metódu, ktorá vráti hodnotu. Ak by ste chceli napísať obslužnú rutinu udalosti, môžete namiesto toho vrátiť void. Až do C # 7.0 mohla asynchrónna metóda vrátiť úlohu, úlohu alebo neplatnosť. Počnúc C # 7.0 môže asynchrónna metóda tiež vrátiť ValueTask (k dispozícii ako súčasť balíka System.Threading.Tasks.Extensions) alebo ValueTask. Tento článok predstavuje diskusiu o tom, ako môžeme pracovať s ValueTask v C #.

Ak chcete pracovať s príkladmi kódu uvedenými v tomto článku, mali by ste mať vo svojom systéme nainštalovanú aplikáciu Visual Studio 2019. Ak ešte nemáte kópiu, môžete si tu stiahnuť Visual Studio 2019.

Vytvorte projekt konzolovej aplikácie .NET Core v Visual Studio

Najprv si vytvoríme projekt konzolovej aplikácie .NET Core v Visual Studio. Za predpokladu, že je vo vašom systéme nainštalované Visual Studio 2019, vytvorte nový projekt konzolovej aplikácie .NET Core v Visual Studio podľa pokynov uvedených nižšie.

  1. Spustite Visual Studio IDE.
  2. Kliknite na „Vytvoriť nový projekt“.
  3. V okne „Vytvoriť nový projekt“ vyberte zo zobrazeného zoznamu šablón „Console App (.NET Core)“.
  4. Kliknite na Ďalej.
  5. V nasledujúcom okne „Konfigurácia nového projektu“ zadajte názov a umiestnenie nového projektu.
  6. Kliknite na tlačidlo Vytvoriť.

Týmto sa vytvorí nový projekt konzolovej aplikácie .NET Core v Visual Studio 2019. Tento projekt použijeme na ilustráciu použitia ValueTask v ďalších častiach tohto článku.

Prečo by som mal používať ValueTask?

Úloha predstavuje stav určitej operácie, t. J. Či je operácia dokončená, zrušená atď. Asynchrónna metóda môže vrátiť Task alebo ValueTask.

Teraz, keďže Task je referenčným typom, vrátenie objektu Task z asynchrónnej metódy znamená alokovať objekt na spravovanej halde pri každom volaní metódy. Jednou z výhrad pri používaní úlohy je, že musíte alokovať pamäť v spravovanej halde zakaždým, keď vrátite objekt Task z vašej metódy. Ak je výsledok operácie vykonanej vašou metódou okamžite k dispozícii alebo sa dokončí synchrónne, toto pridelenie nie je potrebné, a preto sa stáva nákladným.

Presne tu prichádza na pomoc ValueTask. ValueTask poskytuje dve hlavné výhody. Po prvé, ValueTask zlepšuje výkon, pretože nepotrebuje alokáciu haldy, a po druhé, je ľahko a flexibilne implementovateľný. Vrátením ValueTask namiesto Task z asynchrónnej metódy, keď je výsledok okamžite k dispozícii, môžete zabrániť zbytočnej réžii alokácie, pretože „T“ tu predstavuje štruktúru a štruktúra v C # je typ hodnoty (na rozdiel od „T“ v úlohe, ktorá predstavuje triedu).

Task a ValueTask predstavujú dva primárne „očakávané“ typy v C #. Upozorňujeme, že na bloku ValueTask nemôžete blokovať. Ak potrebujete blokovať, mali by ste ValueTask previesť na úlohu pomocou metódy AsTask a potom zablokovať tento referenčný objekt Task.

Upozorňujeme tiež, že každú úlohu ValueTask je možné spotrebovať iba raz. Slovo „konzumovať“ tu znamená, že ValueTask môže asynchrónne čakať na dokončenie (čakať) na operáciu alebo využiť AsTask na prevod ValueTask na úlohu. ValueTask by sa však mal spotrebovať iba raz, potom by sa mal ValueTask ignorovať.

Príklad ValueTask v C #

Predpokladajme, že máte asynchrónnu metódu, ktorá vracia úlohu. Môžete využiť výhodu Task.FromResult na vytvorenie objektu Task, ako je uvedené v útržku kódu uvedenom nižšie.

verejná úloha GetCustomerIdAsync ()

{

návrat Task.FromResult (1);

}

Vyššie uvedený úryvok kódu nevytvára celú mágiu stroja asynchrónneho stavu, ale alokuje objekt úlohy v spravovanej halde. Ak sa chcete vyhnúť tomuto prideleniu, možno budete chcieť namiesto toho využiť výhodu ValueTask, ako je to uvedené v útržku kódu uvedenom nižšie.

verejný ValueTask GetCustomerIdAsync ()

{

vrátiť nový ValueTask (1);

}

Nasledujúci úryvok kódu ilustruje synchrónnu implementáciu ValueTask.

 verejné rozhranie IRepository

    {

ValueTask GetData ();

    }

Trieda Repository rozširuje rozhranie IRepository a implementuje svoje metódy, ako je uvedené nižšie.

  verejná trieda Repository: IRepository

    {

verejný ValueTask GetData ()

        {

var hodnota = predvolená hodnota (T);

vrátiť nový ValueTask (hodnota);

        }

    }

Takto môžete zavolať metódu GetData z hlavnej metódy.

static void Main (reťazec [] args)

        {

IRepository repository = new Repository ();

var result = repository.GetData ();

if (result.IsCompleted)

Console.WriteLine ("Prevádzka dokončená ...");

inak

Console.WriteLine ("Operácia je nedokončená ...");

Console.ReadKey ();

        }

Poďme teraz do nášho úložiska pridať ďalšiu metódu, tentokrát asynchrónnu metódu s názvom GetDataAsync. Takto by vyzeralo upravené rozhranie IRepository.

verejné rozhranie IRepository

    {

ValueTask GetData ();

ValueTask GetDataAsync ();

    }

Metóda GetDataAsync je implementovaná triedou Repository, ako je uvedené v útržku kódu uvedenom nižšie.

  verejná trieda Repository: IRepository

    {

verejný ValueTask GetData ()

        {

var hodnota = predvolená hodnota (T);

vrátiť nový ValueTask (hodnota);

        }

verejná asynchronizácia ValueTask GetDataAsync ()

        {

var hodnota = predvolená hodnota (T);

čaká Task.Delay (100);

návratová hodnota;

        }

    }

Kedy mám použiť ValueTask v C #?

Aj keď výhody, ktoré ValueTask poskytuje, existujú určité kompromisy pri používaní ValueTask namiesto úlohy. ValueTask je typ hodnoty s dvoma poľami, zatiaľ čo Task je referenčný typ s jedným poľom. Používanie ValueTask teda znamená prácu s viacerými údajmi, pretože volanie metódy by namiesto jedného vrátilo dve polia údajov. Tiež, ak čakáte na metódu, ktorá vracia ValueTask, stavový automat pre túto asynchrónnu metódu by bol tiež väčší - pretože by musel v prípade úlohy pojať štruktúru, ktorá obsahuje dve polia namiesto jedného odkazu.

Ďalej, ak spotrebiteľ asynchrónnej metódy používa Task.WhenAll alebo Task.WhenAny, použitie ValueTask ako návratového typu v asynchrónnej metóde môže byť nákladné. Je to tak preto, že by ste potrebovali konvertovať ValueTask na Task pomocou metódy AsTask, čo by malo za následok pridelenie, ktorému by sa dalo ľahko vyhnúť, keby sa na prvom mieste použila Task uložená v pamäti.

Tu platí pravidlo palca. Úlohu použite, keď máte kód, ktorý bude vždy asynchrónny, tj. Keď sa operácia nedokončí okamžite. Využite výhodu ValueTask, keď je už k dispozícii výsledok asynchrónnej operácie alebo keď už máte výsledok v medzipamäti. V každom prípade by ste mali pred vykonaním ValueTask vykonať potrebnú analýzu výkonu.

Ako urobiť viac v C #:

  • Ako používať nemennosť v C.
  • Ako používať const, readonly a static v C #
  • Ako používať dátové anotácie v C #
  • Ako pracovať s identifikátormi GUID v C # 8
  • Kedy použiť abstraktné rozhranie vs. rozhranie v C #
  • Ako pracovať s AutoMapperom v C #
  • Ako používať výrazy lambda v C #
  • Ako pracovať s delegátmi Action, Func a Predicate v C #
  • Ako pracovať s delegátmi v C #
  • Ako implementovať jednoduchý záznamník v C #
  • Ako pracovať s atribútmi v C #
  • Ako pracovať s log4net v C #
  • Ako implementovať vzor návrhu úložiska v C #
  • Ako pracovať s odrazom v C #
  • Ako pracovať so súborovým systémom v C #
  • Ako vykonať lenivú inicializáciu v C #
  • Ako pracovať s MSMQ v C #
  • Ako pracovať s metódami rozšírenia v C #
  • Ako na nás výrazy lambda v C #
  • Kedy použiť volatile kľúčové slovo v C #
  • Ako používať kľúčové slovo výťažku v C #
  • Ako implementovať polymorfizmus v C #
  • Ako zostaviť vlastný plánovač úloh v C #
  • Ako pracovať s RabbitMQ v C #
  • Ako pracovať s n-ticí v C #
  • Skúmanie virtuálnych a abstraktných metód v C #
  • Ako používať Dapper ORM v C #
  • Ako používať návrhový vzor mušej váhy v C #
$config[zx-auto] not found$config[zx-overlay] not found