Denne artikkelen er en speilartikkel om maskinoversettelse, vennligst klikk her for å hoppe til originalartikkelen.

Utsikt: 15343|Svare: 2

[Kommunikasjon] [Oversettelse]. NET for å bruke forskjellen mellom ValueTask og Task

[Kopier lenke]
Publisert 17.03.2022 11:21:50 | | | |


Å bruke Oppgave- eller Oppgaveklasser har en ytelsesflaskehals som vi ikke nevnte i tidligere artikler. Kort sagt, disse klassene leder når resultatene er umiddelbart tilgjengeligeUnødvendig tildeling。 Dette betyr at et nytt Task eller Task-objekt alltid vil bli opprettet, selv om resultatet allerede er tilgjengelig. Nå nevnte vi at async/await-konseptet vi brukte i tidligere artikler har eksistert siden .NET 4.5-lanseringen. Denne funksjonen har blitt forbedret siden C# 7 med .NET 4.7-versjonen med ValueTask-strukturen som kan brukes som retur for asynkrone funksjoner.

ValueTask-struktur


ValueTask-strukturen dukket først opp i corefxlab-arkivet i 2015. Dette arkivet brukes til å eksperimentere og utforske nye ideer som kanskje eller kanskje ikke havner i hoved-corefx-arkivet. Corefx-repositoriet er repositoriet hvor alle .NET Core-basebibliotekene er plassert. Den ble utviklet og foreslått av Stephen Taub for System.Threading.Tasks.Channels-biblioteket. På det tidspunktet ga Stephen en kort forklaring:

corefxlab bibliotekadresse:Innloggingen med hyperkoblingen er synlig.


En ValueTask er en distinkt union av en T og en Task, som gjør det mulig for ReadAsync å fritt allokere for synkront å returnere sine tilgjengelige T-verdier (i motsetning til å bruke Task.FromResult, som krever allokering av en Task-instans). ValueTask er ventebar, så forbruket av de fleste instanser er ikke til å skille fra forbruket av oppgaver.
Mange ser fordelene ved å bruke denne strukturen, som er inkludert i C# 7 som en del av System.Threading.Tasks.Extensions NuGet-pakken. Så, før vi dykker ned i ValueTask-strukturen, la oss se nærmere på problemet den bruker for å løse. Siden Task(Task) er en referansetype, start medDen asynkrone metoden som returnerer Task-objektet betyr at det tildeles på heapen hver gang。 Dette er nødvendig i mange tilfeller.

I noen tilfeller returnerer imidlertid asynkrone metoder resultater umiddelbart eller fullføres synkront. I disse tilfellene er denne tildelingen unødvendig og kan bli kostbar i ytelseskritiske deler av koden. Frem til .NET 4.7-utgivelsen var det ingen måte å unngå dette på, da asynkrone metoder måtte returnere Task, Task <T>eller void (den siste var vanligvis uønsket). I denne versjonen av .NET er dette utvidet, noe som betyr at en asynkron metode kan returnere hvilken som helst type så lenge den har en tilgjengelig GetAwaiter-metode. ValueTask er et konkret eksempel på denne typen, og det ble også lagt til i denne utgivelsen.

Du kan bla gjennom corefx-repositoriet og se hele implementeringen av ValueTask, her er API-delen vi er interessert i:



Som struktur tillater ValueTask å skrive asynkrone metoder som ikke allokerer minne under synkron kjøring. API-konsistensen i async/await-konseptet blir ikke kompromittert på denne måten. I tillegg til dette står denne strukturen alene, noe som gjør den enkel å bruke. For eksempel, hvis vi kjører denne enkle koden:

I MultiplyAsync-metoden simulerer vi en situasjon der vi ønsker å unngå å bruke Task og returnere bare et enkelt heltall. Dette gjøres i metodens if-setning, hvor vi i praksis sjekker om den passerte parameteren er null. Problemet erSelv om betingelsen vår i if-setningen er sann, oppretter koden ovenfor et Task-objekt。 Vi løser dette problemet slik:

ValueTask og Task



Som nevnt tidligere, er det to hovedfordeler med å bruke ValueTask:

  • Ytelsesforbedringer
  • Øk implementeringsfleksibiliteten


Så, hva er tallene bak ytelsesforbedringene? Observer denne koden:


Hvis vi kjører denne koden, tar det 120 ns å kjøre JIT-en. Nå, hvis vi erstatter Task med ValueTask slik:

Med JIT får vi en gjennomføringstid på 65ns. Nå er det sant at på grunn av Task.Delay kjører vi ikke synkront, men vi ser en forbedring i kjøretiden.

En annen fordel vi nevnte er økt fleksibilitet i gjennomføringen. Hva betyr dette egentlig? Vel, implementasjoner av asynkrone grensesnitt som skal synkroniseres, vil bli tvunget til å bruke Task.Run eller Task.FromResult. Selvfølgelig fører dette til ytelsesproblemene vi diskuterte tidligere. Når vi bruker ValueTask, er vi mer tilbøyelige til å velge mellom synkrone eller asynkrone implementasjoner. Husk at dette kan være et tegn på at koden din kanskje ikke er godt designet hvis dette skjer med deg.

For eksempel, observer dette grensesnittet:


La oss si at du vil kalle det fra kode slik:

Fordi vi bruker ValueTask i grensesnittet, kan implementeringen av grensesnittet være synkron eller asynkron. Vi kan få denne fordelen ved i praksis å hoppe over å legge til noen funksjoner i IThing som håndterer synkroniseringsatferd. Det er mye enklere å bruke dette grensesnittet på denne måten. Her er en synkron implementering av grensesnittet ovenfor:

Her er en asynkron implementering av det samme grensesnittet:

Vi må imidlertid vurdere noen avveininger før vi bruker ValueTask. Det er lett å tro at ValueTask bør brukes som standard i stedet for Task, noe som absolutt ikke er tilfelle. For eksempel, selv om ValueTask hjelper oss å unngå unødvendige tildelinger når resultatsynkronisering er tilgjengelig, inneholder det også to felt.

Det er viktig å huske at dette er strukturen vi bruker her, noe som betyr at vi bruker verdityper og alle deres byrder. Oppgave, derimot, er en referansetype med bare ett felt.Når du bruker ValueTask, har vi mer data å behandle og behandle. Hvis en slik metode ventes på i en asynkron metode, så er den asynkrone metodenTilstandsmaskinen vil også være større, fordi lagring av hele strukturen vanligvis krever mer plass enn å lagre en enkelt referanse.

Derfor anbefaler folkene hos Microsoft faktisk å bruke Task eller Task som standard returtype for asynkrone metoder. Først etter ytelsesanalyse bør du vurdere å bytte til ValueTask.


sammendrag

ValueTask er en struktur introdusert i .NET 4.7 som gir oss mange muligheter til å bruke asynkrone metoder i .NET. Men det er ikke uten pris. Dette er nyttig for ytelseskritiske metoder som utføres synkront. Med dem kan vi unngå å tildele unødvendige objekter. Likevel, som en verditype, følger det med alle problemene som verdityper vanligvis har. Derfor kan vi dra nytte av denne strukturen, men vi må være forsiktige.

Opprinnelig adresse:Innloggingen med hyperkoblingen er synlig.




Foregående:【Practical Action】Bruk Docker for å bygge en IPsec VPN-server
Neste:Bruk OpenConnect i stedet for Cisco AnyConnect for å unngå ruting av tabelllåser
Publisert 18.03.2022 kl. 22:21:57 |
Kom for å lære igjen.
Publisert 22.03.2022 kl. 14:05:53 |
Lær essensen av læringIkke dårlig
Ansvarsfraskrivelse:
All programvare, programmeringsmateriell eller artikler publisert av Code Farmer Network er kun for lærings- og forskningsformål; Innholdet ovenfor skal ikke brukes til kommersielle eller ulovlige formål, ellers skal brukerne bære alle konsekvenser. Informasjonen på dette nettstedet kommer fra Internett, og opphavsrettstvister har ingenting med dette nettstedet å gjøre. Du må fullstendig slette innholdet ovenfor fra datamaskinen din innen 24 timer etter nedlasting. Hvis du liker programmet, vennligst støtt ekte programvare, kjøp registrering, og få bedre ekte tjenester. Hvis det foreligger noen krenkelse, vennligst kontakt oss på e-post.

Mail To:help@itsvse.com