Programmēšana

Kad .NET izmantot Task.WaitAll pret Task.WhenAll

TPL (Task Parallel Library) ir viena no interesantākajām jaunajām funkcijām, kas pievienota jaunākajām .NET Framework versijām. Task.WaitAll un Task.WhenAll metodes ir divas svarīgas un TPL bieži izmantotās metodes.

Task.WaitAll bloķē pašreizējo pavedienu, līdz visi citi uzdevumi ir pabeigti. Metode Task.WhenAll tiek izmantota, lai izveidotu uzdevumu, kas tiks izpildīts tikai tad, ja būs izpildīti visi pārējie uzdevumi.

Tātad, ja izmantojat Task.WhenAll, jūs saņemsiet uzdevuma objektu, kas nav pabeigts. Tomēr tas netiks bloķēts, bet ļaus programmu izpildīt. Gluži pretēji, metodes izsaukums Task.WaitAll faktiski bloķē un gaida visu citu uzdevumu izpildi.

Būtībā Task.WhenAll sniegs jums nepabeigtu uzdevumu, taču jūs varat izmantot ContinueWith, tiklīdz norādītie uzdevumi ir izpildīti. Ņemiet vērā, ka ne Task.WhenAll, ne Task.WaitAll faktiski neveiks uzdevumu izpildi; i., ar šīm metodēm netiek uzsākti uzdevumi. Lūk, kā ContinueWith tiek izmantots kopā ar Task.WhenAll:

Task.WhenAll (taskList). Turpiniet ar (t => {

// uzrakstiet savu kodu šeit

});

Kā norādīts Microsoft dokumentācijā, Task.WhenAll “izveido uzdevumu, kas tiks pabeigts, kad būs pabeigti visi uzskaitāmās kolekcijas uzdevuma objekti”.

Task.WhenAll pret Task.WaitAll

Ļaujiet man izskaidrot atšķirību starp šīm divām metodēm ar vienkāršu piemēru. Pieņemsim, ka jums ir uzdevums, kas veic kādu darbību ar lietotāja saskarnes pavedienu - teiksim, lietotāja saskarnē ir jāparāda kāda animācija. Tagad, ja izmantojat Task.WaitAll, lietotāja saskarne tiks bloķēta un netiks atjaunināta, kamēr visi saistītie uzdevumi nebūs izpildīti un bloks atbrīvots. Tomēr, ja izmantojat Task.WhenAll vienā un tajā pašā lietojumprogrammā, lietotāja saskarnes pavediens netiks bloķēts un tiks atjaunināts kā parasti.

Tātad, kuru no šīm metodēm jums vajadzētu izmantot? Varat izmantot WaitAll, ja nodoms sinhroni bloķē, lai iegūtu rezultātus. Bet, kad jūs vēlaties izmantot asinhroniju, jūs vēlaties izmantot variantu WhenAll. Jūs varat gaidīt Task.WhenAll, nebloķējot pašreizējo pavedienu. Tādējādi, iespējams, vēlēsities izmantot gaidīšanu ar Task.WhenAll asinhronās metodes iekšpusē.

Kamēr Task.WaitAll bloķē pašreizējo pavedienu, līdz visi neapstiprinātie uzdevumi ir pabeigti, Task.WhenAll atgriež uzdevuma objektu. Task.WaitAll met AggregateException, kad viens vai vairāki uzdevumi rada izņēmumu. Kad viens vai vairāki uzdevumi rada izņēmumu un jūs gaida Task.WhenAll metodi, tā atritina AggregateException un atgriež tikai pirmo.

Izvairieties no uzdevuma izmantošanas. Palaidiet cilpās

Uzdevumus varat izmantot, kad vēlaties veikt vienlaicīgas darbības. Ja jums nepieciešama augsta līmeņa paralēle, uzdevumi nekad nav laba izvēle. Vienmēr ieteicams izvairīties no pavedienu kopas pavedienu izmantošanas ASP.Net. Tādēļ jums vajadzētu atturēties no Task.Run vai Task.factory.StartNew izmantošanas ASP.Net.

Uzdevums Run vienmēr jāizmanto CPU saistītam kodam. Task.Run nav laba izvēle ASP.Net lietojumprogrammās vai lietojumprogrammās, kas izmanto ASP.Net izpildlaiku, jo tas vienkārši izlādē darbu ThreadPool pavedienam. Ja izmantojat ASP.Net Web API, pieprasījums jau izmanto ThreadPool pavedienu. Tādējādi, ja ASP.Net Web API lietojumprogrammā izmantojat Task.Run, jūs vienkārši ierobežojat mērogojamību, izkraujot darbu citam darbinieka pavedienam bez jebkāda iemesla.

Ņemiet vērā, ka, izmantojot uzdevumu, palaidiet cilni. Ja cikla iekšpusē izmantojat metodi Task.Run, tiks izveidoti vairāki uzdevumi - pa vienam katrai darba vienībai vai atkārtojumam. Tomēr, ja izmantojat Parallel.ForEach, nevis Task.Run, izmantojot cilpu, tiek izveidots sadalītājs, lai neradītu vairāk uzdevumu, lai veiktu darbību, nekā nepieciešams. Tas var ievērojami uzlabot veiktspēju, jo jūs varat izvairīties no pārāk daudz konteksta slēdžu un joprojām izmantot vairākus kodolus savā sistēmā.

Jāatzīmē, ka Parallel.ForEach izmanto sadalītāju iekšēji, lai kolekciju sadalītu darba priekšmetos. Starp citu, šis sadalījums nenotiek katram uzdevumu vienumu sarakstā, drīzāk tas notiek kā pakete. Tas samazina iesaistītās izmaksas un tādējādi uzlabo veiktspēju. Citiem vārdiem sakot, ja izmantojat cilni Task.Run vai Task.Factory.StartNew, viņi skaidri izveidos jaunus uzdevumus katrai cilpas iterācijai. Parallel.ForEach ir daudz efektīvāka, jo tā optimizēs izpildi, sadalot darba slodzi vairākos sistēmas kodolos.

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