Programmering

Når skal jeg bruke Task.WaitAll vs. Task.WhenAll i .NET

TPL (Task Parallel Library) er en av de mest interessante nye funksjonene som er lagt til i de nyeste versjonene av .NET framework. Task.WaitAll og Task.WhenAll-metodene er to viktige og ofte brukte metoder i TPL.

Task.WaitAll blokkerer den gjeldende tråden til alle andre oppgaver er fullført. Task.WhenAll-metoden brukes til å lage en oppgave som fullføres hvis og bare hvis alle de andre oppgavene er fullført.

Så hvis du bruker Task.WhenAll får du et oppgaveobjekt som ikke er komplett. Imidlertid vil det ikke blokkere, men vil tillate at programmet kjøres. Tvert imot blokkerer og venter Task.WaitAll-metodeanropet på at alle andre oppgaver skal fullføres.

I hovedsak vil Task.WhenAll gi deg en oppgave som ikke er fullført, men du kan bruke ContinueWith så snart de angitte oppgavene er fullført. Merk at verken Task.WhenAll eller Task.WaitAll faktisk kjører oppgavene; dvs. ingen oppgaver startes av disse metodene. Slik brukes ContinueWith med Task.WhenAll:

Task.WhenAll (taskList) .ContinueWith (t => {

// skriv koden din her

});

Som Microsofts dokumentasjon sier, oppretter Task.WhenAll en oppgave som fullføres når alle oppgaveobjektene i en utallig samling er fullført.

Task.WhenAll vs. Task.WaitAll

La meg forklare forskjellen mellom disse to metodene med et enkelt eksempel. Anta at du har en oppgave som utfører litt aktivitet med UI-tråden - si at noen animasjoner må vises i brukergrensesnittet. Nå, hvis du bruker Task.WaitAll, vil brukergrensesnittet bli blokkert og vil ikke bli oppdatert før alle relaterte oppgaver er fullført og blokken utgitt. Imidlertid, hvis du bruker Task.WhenAll i samme applikasjon, vil ikke UI-tråden bli blokkert og vil bli oppdatert som vanlig.

Så hvilken av disse metodene bør du bruke når? Vel, du kan bruke WaitAll når intensjonen blokkeres synkront for å få resultatene. Men når du ønsker å utnytte asynkroni, vil du bruke WhenAll-varianten. Du kan avvente Task.WhenAll uten å måtte blokkere den gjeldende tråden. Derfor kan det være lurt å bruke Wait med Task.WhenAll i en asynkroniseringsmetode.

Mens Task.WaitAll blokkerer den gjeldende tråden til alle ventende oppgaver er fullført, returnerer Task.WhenAll et oppgaveobjekt. Task.WaitAll kaster et AggregateException når en eller flere av oppgavene gir et unntak. Når en eller flere oppgaver kaster et unntak, og du venter på Task.WhenAll-metoden, pakker den ut AggregateException og returnerer bare den første.

Unngå å bruke Task. Kjør i løkker

Du kan bruke oppgaver når du ønsker å utføre samtidige aktiviteter. Hvis du trenger en høy grad av parallellitet, er oppgaver aldri et godt valg. Det anbefales alltid å unngå å bruke trådgruppetråder i ASP.Net. Derfor bør du avstå fra å bruke Task.Run eller Task.factory.StartNew i ASP.Net.

Task.Run skal alltid brukes til CPU-bundet kode. Task.Run er ikke et godt valg i ASP.Net-applikasjoner, eller applikasjoner som utnytter ASP.Net-kjøretiden siden den bare avlaster arbeidet til en ThreadPool-tråd. Hvis du bruker ASP.Net Web API, vil forespørselen allerede bruke en ThreadPool-tråd. Derfor, hvis du bruker Task.Run i ASP.Net Web API-applikasjonen din, begrenser du bare skalerbarhet ved å laste ned arbeidet til en annen arbeidertråd uten grunn.

Merk at det er en ulempe ved å bruke Task.Run i en løkke. Hvis du bruker Task.Run-metoden i en løkke, vil det opprettes flere oppgaver - en for hver arbeidsenhet eller iterasjon. Imidlertid, hvis du bruker Parallel.ForEach i stedet for å bruke Task.Run i en løkke, blir en Partitioner opprettet for å unngå å opprette flere oppgaver for å utføre aktiviteten enn den er nødvendig. Dette kan forbedre ytelsen betydelig, ettersom du kan unngå for mange kontekstbrytere og fremdeles utnytte flere kjerner i systemet ditt.

Det skal bemerkes at Parallel.ForEach bruker Partitioner internt for å distribuere samlingen i arbeidsartikler. Forresten, denne fordelingen skjer ikke for hver oppgave i listen over varer, men det skjer som en batch. Dette senker de involverte omkostningene og forbedrer dermed ytelsen. Med andre ord, hvis du bruker Task.Run eller Task.Factory.StartNew i en løkke, vil de opprette nye oppgaver eksplisitt for hver iterasjon i løkken. Parallel.ForEach er mye mer effektivt fordi det vil optimalisere utførelsen ved å fordele arbeidsbelastningen over flere kjerner i systemet ditt.

$config[zx-auto] not found$config[zx-overlay] not found