Dit artikel is een spiegelartikel van machinevertaling, klik hier om naar het oorspronkelijke artikel te gaan.

Bekijken: 15343|Antwoord: 2

[Communicatie] [Vertaling]. NET om het verschil tussen ValueTask en Task te gebruiken

[Link kopiëren]
Geplaatst op 2022-3-17 11:21:50 | | | |


Het gebruik van Taak of Taakklassen heeft een prestatieknelpunt die we in eerdere artikelen niet hebben genoemd. Kortom, deze lessen leiden wanneer de resultaten direct beschikbaar zijnOnnodige toewijzing。 Dit betekent dat er altijd een nieuw Taak- of Taakobject wordt aangemaakt, zelfs als het resultaat al beschikbaar is. We hebben al gezegd dat het async/await-concept dat we in eerdere artikelen gebruikten al bestaat sinds de release van .NET 4.5. Deze functie is sinds C# 7 verbeterd met de .NET 4.7-versie met de ValueTask-structuur die kan worden gebruikt als return voor asynchrone functies.

ValueTask-structuur


De ValueTask-structuur verscheen voor het eerst in de corefxlab-repository in 2015. Deze repository wordt gebruikt om te experimenteren en nieuwe ideeën te verkennen die mogelijk wel of niet in de hoofd-corefx-repository terechtkomen. De Corefx-repository is de repository waar alle .NET Core-basisbibliotheken zich bevinden. Het werd ontwikkeld en aanbevolen door Stephen Taub voor de System.Threading.Tasks.Channels-bibliotheek. Op dat moment gaf Stephen een korte uitleg:

CoreFXLab-bibliotheekadres:De hyperlink-login is zichtbaar.


Een ValueTask is een aparte unie van een T en een Task, waardoor ReadAsync vrij de beschikbare T-waarden kan toewijzen om synchroon terug te geven (in tegenstelling tot het gebruik van Task.FromResult, waarvoor een toewijzing van een Task-instantie vereist is). ValueTask is wachtbaar, dus het verbruik van de meeste instanties is niet te onderscheiden van het verbruik van taken.
Veel mensen zien de voordelen van het gebruik van deze structuur, die is opgenomen in C# 7 als onderdeel van het System.Threading.Tasks.Extensions NuGet-pakket. Dus, voordat we ingaan op de ValueTask-structuur, laten we het probleem bekijken waarmee deze wordt gebruikt. Aangezien Task(Task) een referentietype is, begin je metDe asynchrone methode die het Task-object teruggeeft betekent dat het elke keer op de heap wordt toegewezen。 Dit is in veel gevallen noodzakelijk.

In sommige gevallen geven asynchrone methoden echter direct resultaten terug of voltooien ze synchroon. In deze gevallen is deze toewijzing onnodig en kan het duur worden in prestatiekritische delen van de code. Tot de .NET 4.7-release was er geen manier om dit te vermijden, omdat asynchrone methoden Task, Task <T>of void moesten teruggeven (de laatste was meestal ongewenst). In deze versie van .NET is dit uitgebreid, wat betekent dat een asynchrone methode elk type kan teruggeven zolang er een toegankelijke GetAwaiter-methode is. ValueTask is een concreet voorbeeld van dit type en is ook toegevoegd aan deze release.

Je kunt de corefx-repository bekijken en de volledige implementatie van ValueTask bekijken, hier is de API-sectie waarin we geïnteresseerd zijn:



Als structuur maakt ValueTask het mogelijk om asynchrone methoden te schrijven die geen geheugen toewijzen tijdens synchrone runtime. De API-consistentie van het async/await-concept wordt op deze manier niet aangetast. Daarnaast wacht deze structuur op zichzelf, waardoor het gebruiksvriendelijk is. Bijvoorbeeld, als we deze eenvoudige code uitvoeren:

In de MultiplyAsync-methode simuleren we een situatie waarin we Task willen vermijden en slechts een eenvoudig geheel getal willen teruggeven. Dit gebeurt in de if-instructie van de methode, waarbij we in feite controleren of de doorgegeven parameter nul is. Het probleem isZelfs als onze voorwaarde in de if-stelling waar is, creëert de bovenstaande code een Taakobject。 We lossen dit probleem op als volgt:

ValueTask en Task



Zoals eerder genoemd, zijn er twee belangrijke voordelen aan het gebruik van ValueTask:

  • Prestatieverbeteringen
  • Verhoog de flexibiliteit in de implementatie


Dus, wat zijn de cijfers achter de prestatieverbeteringen? Let op deze code:


Als we deze code draaien, kost het 120ns om de JIT uit te voeren. Als we Task nu vervangen door ValueTask als volgt:

Met JIT krijgen we een uitvoeringstijd van 65ns. Het is waar dat we door Task.Delay niet synchroon uitvoeren, maar we zien een verbetering in uitvoeringstijd.

Een ander voordeel dat we noemden is de grotere flexibiliteit in de uitvoering. Wat betekent dit precies? Implementaties van asynchrone interfaces die gesynchroniseerd moeten zijn, zullen gedwongen worden Task.Run of Task.FromResult te gebruiken. Natuurlijk leidt dit tot de prestatieproblemen die we eerder bespraken. Wanneer we ValueTask gebruiken, kiezen we eerder tussen synchrone of asynchrone implementaties. Houd er rekening mee dat dit een teken kan zijn dat je code misschien niet goed ontworpen is als dit jou overkomt.

Observer bijvoorbeeld deze interface:


Stel dat je het vanuit de code als volgt wilt noemen:

Omdat we ValueTask in de interface gebruiken, kan de implementatie van de interface synchroon of asynchroon zijn. We kunnen dit voordeel halen door in feite het toevoegen van enkele functies aan IThing over te slaan die het synchronisatiegedrag afhandelen. Het is op deze manier veel makkelijker om deze interface te gebruiken. Hier is een synchrone implementatie van bovenstaande interface:

Hier is een asynchrone implementatie van dezelfde interface:

We moeten echter enkele afwegingen overwegen voordat we ValueTask gebruiken. Het is makkelijk te denken dat ValueTask standaard gebruikt moet worden in plaats van Task, wat zeker niet het geval is. Zo helpt ValueTask ons onnodige toewijzingen te vermijden wanneer resultaatsynchronisatie beschikbaar is, maar bevat het ook twee velden.

Het is belangrijk te onthouden dat dit de structuur is die we hier gebruiken, wat betekent dat we waardetypes en al hun lasten gebruiken. Taak daarentegen is een referentietype met slechts één veld.Wanneer je ValueTask gebruikt, hebben we meer data om te verwerken en te verwerken. Als op zo'n methode wordt gewacht in een asynchrone methode, dan is de asynchrone methodeDe toestandsmachine zal ook groter zijn, omdat het opslaan van de gehele structuur meestal meer ruimte vereist dan het opslaan van één enkele referentie.

Daarom raden de mensen bij Microsoft eigenlijk aan om Task of Task als standaard retourtype voor asynchrone methoden te gebruiken. Pas na een prestatieanalyse zou je moeten overwegen over te stappen naar ValueTask.


samenvatting

ValueTask is een structuur die in .NET 4.7 is geïntroduceerd en ons veel mogelijkheden biedt om asynchrone methoden in .NET te gebruiken. Toch is het niet zonder prijs. Dit is nuttig voor prestatiekritische methoden die synchroon worden uitgevoerd. Met hen kunnen we het toewijzen van onnodige objecten vermijden. Toch brengt het als waardetype alle problemen met zich mee die waardetypes meestal hebben. Daarom kunnen we profiteren van deze structuur, maar we moeten voorzichtig zijn.

Origineel adres:De hyperlink-login is zichtbaar.




Vorig:【Practical Action】Gebruik Docker om een IPsec VPN-server te bouwen
Volgend:Gebruik OpenConnect in plaats van Cisco AnyConnect om routeringstabelvergrendelingen te vermijden
Geplaatst op 18-03-2022 22:21:57 |
Kom weer leren om te leren.
Geplaatst op 22-3-2022 14:05:53 |
Leer de essentie van lerenNiet slecht
Disclaimer:
Alle software, programmeermaterialen of artikelen die door Code Farmer Network worden gepubliceerd, zijn uitsluitend bedoeld voor leer- en onderzoeksdoeleinden; De bovenstaande inhoud mag niet worden gebruikt voor commerciële of illegale doeleinden, anders dragen gebruikers alle gevolgen. De informatie op deze site komt van het internet, en auteursrechtconflicten hebben niets met deze site te maken. Je moet bovenstaande inhoud volledig van je computer verwijderen binnen 24 uur na het downloaden. Als je het programma leuk vindt, steun dan de echte software, koop registratie en krijg betere echte diensten. Als er sprake is van een inbreuk, neem dan contact met ons op via e-mail.

Mail To:help@itsvse.com