Acest articol este un articol oglindă al traducerii automate, vă rugăm să faceți clic aici pentru a sări la articolul original.

Vedere: 42759|Răspunde: 5

[Sursă] De ce este sarcina .net/c# mai lentă decât Thread?

[Copiază linkul]
Postat pe 03.05.2017 16:40:28 | | | |
.NET 4 include un nou spațiu de nume, System.Threading.Tasks, care conține clase ce abstractizează funcționalitatea threading-ului. Folosește ThreadPool în fundal. O sarcină reprezintă munca unei unități care trebuie finalizată. Munca acestei unități poate fi executată într-un fir separat sau o sarcină poate fi începută sincron, ceea ce necesită așteptarea firului principal de reglaj. Folosirea sarcinilor nu doar că îți oferă un strat de abstractizare, dar îți oferă și mult control asupra firelor de execuție subiacente.
Sarcinile oferă multă flexibilitate când vine vorba de programarea muncii care trebuie făcute. De exemplu, poți defini o sarcină continuă – ce muncă trebuie făcută după ce o sarcină este finalizată. Acest lucru poate face diferența între o sarcină reușită și o nu. În plus, sarcinile pot fi aranjate într-o ierarhie. De exemplu, o sarcină părinte poate crea o nouă sarcină copil. Aceasta creează o dependență astfel încât, dacă anulezi sarcina părinte, sarcina copilului va fi de asemenea anulată.


În zilele noastre, este popular să folosești metode de execuție a sarcinilor, iar acestea sunt de înaltă performanță, iar eu nu știu unde este performanța sarcinii.

Am testat personal Task și Thread și simt că Task este foarte lent, ceea ce afectează mult performanța, iar codul de test este următorul:

Parcurgem metoda de 1000 de ori, apoi metoda blochează timp de 100 de milisecunde, iar rezultatul testului este următorul:



Rezultat:
Execuția firului durează 188 de milisecunde
Executarea sarcinii durează 14.671 milisecunde


Diferența de viteză dintre cele două este de 78 de ori!!

Sarcina este foarte lentă, nu știu de ce se întâmplă asta, există ceva în neregulă cu codul meu de test sau ce? Sper că poți explica de ce se întâmplă asta...




Precedent:Trimite mesaje cu ASP.NET Core
Următor:C# Calcul paralel Paralel.For&Parallel.For
 Proprietarul| Postat pe 13.10.2020 10:47:17 |
tongli1996218 Postat la 2020-10-13 09:34
Pentru a asigura același cod ca Thread, operațiunea mea este următorul cod, iar cele de mai sus sunt pseudo-cod
PS: Doar sună, așteaptă Sarcina. Întârzie fără a adăuga ...

Da, mulțumesc

Timpul de execuție al sarcinii: 117.0357

Poți modifica codul astfel:

Task.Run înlocuiește Task.Factory.StartNew deoarece despachetează automat sarcinile interne.
Task.WaitAll așteaptă o sarcină externă în loc de una internă. Folosirea Task.Run nu are sarcini imbricate.


Privind documentația msdn, poți vedea că metoda Task.Delay Method creează o sarcină care se finalizează după un număr specificat de milisecunde. (De fapt, va fi creat un fir nou și va fi adăugat await pentru a aștepta executarea sarcinii, nu știu dacă am înțeles corect)

Autentificarea cu hyperlink este vizibilă.

În plus, există o diferență între Task și void

Sarcina returnează o metodă asincronă care poate aștepta
Metoda void return asincronă nu poate aștepta, funcționează asincron, nu poți ști când s-a terminat, nu poți monitoriza starea acelei operații asincrone.


Referință:

Autentificarea cu hyperlink este vizibilă.
Autentificarea cu hyperlink este vizibilă.

În rezumat: există o problemă cu codul, nu ar trebui să folosesc Thread.Sleep în interiorul metodei Task
Postat pe 21.07.2020 13:09:29 |
Am avut aceeași problemă azi, folosind multithreading pentru criptare AES, Task este mult mai lent decât Thread!!
Proprietarul a găsit motivul?
Postat pe 12.10.2020 19:24:48 |
Această postare a fost editată ultima dată de tongli1996218 la 2020-10-12 19:43

După testarea codului proprietarului, când programul este pornit și rulat de mai multe ori, timpul sarcinii va continua să scadă, iar pe calculatorul meu va fi redus la mai puțin decât Thread, iar Thread rămâne stabil în acest timp.

Ulterior s-a constatat că metoda Thread.Sleep(100) avea un impact negativ asupra Sarciunii, dar nu și asupra Firului, iar Thread.Sleep(100) putea fi înlocuit cu alte verificări de program consumatoare de timp, cum ar fi auto-adunarea numerică sau await Task.Delay(100).

PS: Thread.Sleep va încheia timpul curent de tăiere a firului după apelare, de exemplu Thread.Sleep(0) va încheia timpul curent de tăiere a firului și îl va transfera către alte fire pentru a rula. În interiorul sarcinii se află un pool de fire, care poate optimiza comutarea contextului firelor și reduce timpul de pierdere a CPU-ului (mai ales pentru optimizarea CPU multi-core), în timp ce Thread.Sleep(100) va perturba logica de comutare a pool-ului original de thread al sarcinii, cauzând pierderi semnificative de timp de proces

Dacă înlocuiești Thread.Sleep(100) cu await Task.Delay(100), vei observa că consumul de timp al sarcinii este doar mai mare de 100 milisecunde, așa cum se arată mai jos:
private void TaskTest()
{
        Thread.Sleep(100);
         ... Execută acțiunea
}
Înlocuit de
privat async void TaskTest()
{
      așteaptă Sarcina. Întârziere(100);
      ... Execuția durează mai mult de 100 de milisecunde pentru această sarcină, ceea ce este același cu Thread.Sleep(100) original pentru Thread
}




 Proprietarul| Postat pe 12.10.2020 22:53:05 |
tongli1996218 Postat la 2020-10-12 19:24
După testarea codului proprietarului, când programul este pornit, timpul sarcinii va continua să scadă după ce rulezi de mai multe ori, iar pe calculatorul meu va fi redus la mai puțin decât Thread...

Am încercat să schimb codul așa:
Sarcină. Întârziere(100000);

Timpul de execuție al sarcinii:14,1306 ms, timpul total este într-adevăr foarte scurt, însă am constatat că metoda apelată de Task nu a finalizat execuția.
Postat pe 13.10.2020 09:34:33 |
Această postare a fost editată ultima dată de tongli1996218 la 2020-10-13 09:40
Publicat la 2020-10-12, 22:53
Am încercat să schimb codul așa:
Sarcină.Întârziere(100000);

Pentru a asigura același cod ca Thread, operațiunea mea este următorul cod, iar cele de mai sus sunt pseudo-cod
PS: Pur și simplu apelează await Task.Delay, apoi adaugă niciun cod, firul deschis de sarcină este returnat imediat, pentru a asigura simularea compute-bound, poți folosi pentru (int a = 0; a< 1000000; ++a){}; Astfel de metode în schimb

privat async static void TaskTest()
        {
            așteaptă Sarcina. Întârziere(100000);
             Interblocat. Increment (rundă de referință);    încuietoare, dar deasupra este mai mică
            if(run == j)
             {
                Cronometru. Stop(); Opriți monitorizarea
                TimeSpan = cronometru. A trecut;  Obține timpul total măsurat de instanța curentă
                Console.WriteLine ("Timp de execuție a sarcinii:" + interval de timp. TotalMilisecunde); Milisecunde totale
              }
        Timpul consumat este, de asemenea, foarte scurt


Disclaimer:
Tot software-ul, materialele de programare sau articolele publicate de Code Farmer Network sunt destinate exclusiv scopurilor de învățare și cercetare; Conținutul de mai sus nu va fi folosit în scopuri comerciale sau ilegale, altfel utilizatorii vor suporta toate consecințele. Informațiile de pe acest site provin de pe Internet, iar disputele privind drepturile de autor nu au legătură cu acest site. Trebuie să ștergi complet conținutul de mai sus de pe calculatorul tău în termen de 24 de ore de la descărcare. Dacă îți place programul, te rugăm să susții software-ul autentic, să cumperi înregistrarea și să primești servicii autentice mai bune. Dacă există vreo încălcare, vă rugăm să ne contactați prin e-mail.

Mail To:help@itsvse.com