Šis straipsnis yra veidrodinis mašininio vertimo straipsnis, spauskite čia norėdami pereiti prie originalaus straipsnio.

Rodinys: 42759|Atsakyti: 5

[Šaltinis] Kodėl .net/c# užduotis yra lėtesnė nei "Thread"?

[Kopijuoti nuorodą]
Paskelbta 2017-05-03 16:40:28 | | | |
.NET 4 apima naują vardų sritį System.Threading.Tasks, kurioje yra klasės, abstrahuojančios gijų funkciją. Naudokite "ThreadPool" fone. Užduotis nurodo vieneto darbą, kurį reikia atlikti. Šio įrenginio darbas gali būti vykdomas atskiroje gijoje arba užduotis gali būti pradėta sinchroniškai, todėl reikia laukti pagrindinės derinimo gijos. Užduočių naudojimas ne tik suteikia abstrakcijos sluoksnį, bet ir suteikia daug galimybių valdyti pagrindines gijas.
Užduotys suteikia daug lankstumo planuojant darbus, kuriuos reikia atlikti. Pavyzdžiui, galite apibrėžti tęstinę užduotį – koks darbas turi būti atliktas atlikus užduotį. Tai gali lemti sėkmingą užduotį ir ne. Be to, užduotys gali būti išdėstytos hierarchijoje. Pavyzdžiui, pirminė užduotis gali sukurti naują antrinę užduotį. Taip sukuriama priklausomybė, kad atšaukus pirminę užduotį, bus atšaukta ir jos antrinė užduotis.


Šiais laikais populiaru naudoti užduočių vykdymo metodus, jie yra didelio našumo, ir nežinau, kur yra užduočių atlikimas.

Aš pats išbandžiau užduotį ir giją, ir manau, kad užduotis yra labai lėta, o tai labai veikia našumą, o bandymo kodas yra toks:

Mes pereiname metodą 1000 kartų, tada metodas blokuojamas 100 milisekundžių, o testo rezultatas yra toks:



Rezultatus:
Gijos vykdymas trunka 188 milisekundes
Užduoties vykdymas trunka 14 671 milisekundę


Greičio skirtumas tarp jų yra 78 kartus!!

Užduotis yra labai lėta, nežinau, kodėl tai vyksta, ar kažkas negerai su mano bandomuoju kodu, ar ką? Tikiuosi, kad galite paaiškinti, kodėl taip atsitinka...




Ankstesnis:Siųskite pranešimus naudodami "ASP.NET Core"
Kitą:C# Lygiagretus skaičiavimas Parallel.For&Parallel.For
 Savininkas| Paskelbta 2020-10-13 10:47:17 |
tongli1996218 Nusiųsta: 2020-10-13 09:34
Norint užtikrinti tą patį kodą kaip ir Thread, mano operacija yra šis kodas, o aukščiau pateiktas yra pseudokodas
PS: Tiesiog skambinkite laukti Task.Delay nepridedant ...

Taip, ačiū

Užduoties vykdymo laikas: 117.0357

Kodą galite modifikuoti taip:

Task.Run pakeičia Task.Factory.StartNew, nes automatiškai išpakuoja vidines užduotis.
Task.WaitAll laukia išorinės, o ne vidinės užduoties. Naudojant Task.Run įdėtųjų užduočių nėra.


Pažvelgę į msdn dokumentaciją galite pamatyti, kad Task.Delay metodo metodas sukuria užduotį, kuri baigiama po nurodyto milisekundžių skaičiaus. (Tiesą sakant, bus sukurta nauja gija ir laukti, kol užduotis bus įvykdyta, nežinau, ar teisingai suprantu)

Hipersaito prisijungimas matomas.

Be to, yra skirtumas tarp užduoties ir tuštumos

Užduotis pateikia asinchroninį metodą, kuris gali palaukti
Void return asinchroninis metodas negali laukti, jis veikia asinchroniškai, jūs negalite žinoti, kada tai padaryta, jūs negalite stebėti tos asinchroninės operacijos būsenos.


Nuoroda:

Hipersaito prisijungimas matomas.
Hipersaito prisijungimas matomas.

Apibendrinant: yra problema su kodu, aš neturėčiau naudoti Thread.Sleep viduje Task metodas
Paskelbta 2020-07-21 13:09:29 |
Aš turėjau tą pačią problemą šiandien, naudojant multithreading AES šifravimas, užduotis yra daug lėtesnė nei Thread!
Ar nuomotojas rado priežastį?
Paskelbta 2020-10-12 19:24:48 |
Šį pranešimą paskutinį kartą redagavo tongli1996218 2020-10-12 19:43

Išbandžius savininko kodą, kai programa paleidžiama ir paleidžiama kelis kartus, užduoties laikas ir toliau mažės, o mano kompiuteryje jis bus sumažintas iki mažiau nei "Thread", o "Thread" per tą laiką yra stabilus.

Vėliau buvo nustatyta, kad Thread.Sleep(100) metodas turėjo neigiamą poveikį Task, bet ne Thread, ir Thread.Sleep(100) galėjo būti pakeistas kitu daug laiko reikalaujančiu programos patikrinimu, pvz., skaitmeniniu savęs pridėjimu arba laukti Task.Delay(100).

PS: Thread.Sleep baigs dabartinį gijų pjaustymo laiką po iškvietimo, pvz., Thread.Sleep(0) baigs dabartinį gijų pjaustymo laiką ir perkels jį į kitas gijas, kad paleistų. Užduoties viduje yra gijų telkinys, kuris gali optimizuoti gijų konteksto perjungimą ir sumažinti procesoriaus praradimo laiką (ypač kelių branduolių procesoriaus optimizavimui), o Thread.Sleep(100) sutrikdys pradinio užduoties gijų telkinio perjungimo logiką, sukeldamas daug procesoriaus laiko praradimo

Jei pakeisite Thread.Sleep(100) į laukti Task.Delay(100), pamatysite, kad užduoties laiko sąnaudos yra tik daugiau nei 100 milisekundžių, kaip parodyta toliau:
privati void TaskTest()
{
        Thread.Sleep(100);
         ... Atlikite veiksmą
}
Pakeista taip:
privatus asinchroninis void TaskTest()
{
      laukti Task.Delay(100);
      ... Užduoties vykdymas trunka daugiau nei 100 milisekundžių, o tai yra tas pats, kaip ir originalus Thread.Sleep(100)
}




 Savininkas| Paskelbta 2020-10-12 22:53:05 |
tongli1996218 Publikuota 2020-10-12 19:24
Išbandžius savininko kodą, paleidus programą, užduoties laikas ir toliau mažės paleidus kelis kartus, o mano kompiuteryje jis bus sumažintas iki mažiau nei Thread...

Aš bandžiau pakeisti jį į kodą taip:
Užduotis.Vėlavimas(100000);

Užduoties vykdymo laikas:14,1306 ms, bendras laikas iš tiesų yra labai trumpas, tačiau pastebėjau, kad užduoties iškviestas metodas neužbaigė vykdymo.
Paskelbta 2020-10-13 09:34:33 |
Šį pranešimą paskutinį kartą redagavo tongli1996218 2020-10-13 09:40
Publikuota 2020-10-12 22:53
Aš bandžiau pakeisti jį į kodą taip:
Užduotis.Vėlavimas(100000);

Norint užtikrinti tą patį kodą kaip ir Thread, mano operacija yra šis kodas, o aukščiau pateiktas yra pseudokodas
PS: Tiesiog skambinkite laukti Task.Delay, ir tada pridėti ne kodas, gija atidaryta užduotis yra grąžinta nedelsiant, siekiant užtikrinti modeliavimą skaičiavimo, galite naudoti (int a = 0; a< 1000000; ++a){}; Tokie metodai vietoj to

privatus asinchroninis statinis void TaskTest()
        {
            laukti Task.Delay(100000);
             Interlocked.Increment (nuorodos vykdymas);    užraktas, bet viršutinė dalis yra mažesnė
            if(paleisti == j)
             {
                chronometras. Stop(); Sustabdyti stebėjimą
                TimeSpan laiko intervalas = chronometras. Praėjo;  Gauna bendrą dabartinio egzemplioriaus išmatuotą laiką
                Console.WriteLine("Užduoties vykdymo laikas:" + laiko tarpas. TotalMilliseconds); Iš viso milisekundžių
              }
        Sunaudotas laikas taip pat yra labai trumpas


Atsakomybės apribojimas:
Visa programinė įranga, programavimo medžiaga ar straipsniai, kuriuos skelbia Code Farmer Network, yra skirti tik mokymosi ir mokslinių tyrimų tikslams; Aukščiau nurodytas turinys negali būti naudojamas komerciniais ar neteisėtais tikslais, priešingu atveju vartotojai prisiima visas pasekmes. Šioje svetainėje pateikiama informacija gaunama iš interneto, o ginčai dėl autorių teisių neturi nieko bendra su šia svetaine. Turite visiškai ištrinti aukščiau pateiktą turinį iš savo kompiuterio per 24 valandas nuo atsisiuntimo. Jei jums patinka programa, palaikykite autentišką programinę įrangą, įsigykite registraciją ir gaukite geresnes autentiškas paslaugas. Jei yra kokių nors pažeidimų, susisiekite su mumis el. paštu.

Mail To:help@itsvse.com