Denne artikel er en spejling af maskinoversættelse, klik venligst her for at springe til den oprindelige artikel.

Udsigt: 42759|Svar: 5

[Kilde] Hvorfor er .net/c# Task langsommere end Thread?

[Kopier link]
Opslået på 03/05/2017 16.40.28 | | | |
.NET 4 inkluderer et nyt navnerum, System.Threading.Tasks, som indeholder klasser, der abstraherer trådningsfunktionalitet. Brug ThreadPool i baggrunden. En opgave repræsenterer arbejdet i en enhed, der skal udføres. Arbejdet med denne enhed kan køres i en separat tråd, eller en opgave kan startes synkront, hvilket kræver ventetid på hovedtuningtråden. At bruge opgaver giver dig ikke kun et abstraktionslag, men også meget kontrol over de underliggende tråde.
Opgaver giver stor fleksibilitet, når det gælder planlægning af det arbejde, der skal udføres. For eksempel kan du definere en kontinuerlig opgave – hvilket arbejde der skal udføres efter en opgave er afsluttet. Dette kan være forskellen på en succesfuld opgave eller ej. Derudover kan opgaver arrangeres i et hierarki. For eksempel kan en forældreopgave oprette en ny underopgave. Dette skaber en afhængighed, så hvis du annullerer forældreopgaven, vil dens underopgave også blive annulleret.


I dag er det populært at bruge metoder til opgaveudførelse, og det er højtydende, og jeg ved ikke, hvor opgavepræstationen er.

Jeg testede selv Task og Thread, og jeg føler, at Task er meget langsom, hvilket i høj grad påvirker ydeevnen, og testkoden er som følger:

Vi kører metoden 1000 gange, og derefter blokerer metoden i 100 millisekunder, og testresultatet er som følger:



Udfald:
Trådeksekveringen tager 188 millisekunder
Opgaveudførelsen tager 14.671 millisekunder


Hastighedsforskellen mellem de to er 78 gange!!

Opgaven er meget langsom, jeg ved ikke hvorfor det sker, er der noget galt med min testkode, eller hvad? Jeg håber, du kan forklare, hvorfor det sker...




Tidligere:Send beskeder med ASP.NET Core
Næste:C# Parallel beregning Parallel.For&Parallel.For
 Udlejer| Opslået på 13/10/2020 10.47.17 |
tongli1996218 Opslået den 13-10-2020 09:34
For at sikre samme kode som Thread, er min operation følgende kode, og ovenstående er pseudokode
PS: Bare kald await Task.Delay uden at tilføje ...

Ja, tak

Opgaveudførelsestid: 117,0357

Du kan ændre koden som følger:

Task.Run erstatter Task.Factory.StartNew, fordi den automatisk udpakker interne opgaver.
Task.WaitAll venter på en ekstern opgave i stedet for en intern. At bruge Task.Run har ikke indlejrede opgaver.


Hvis du kigger i msdn-dokumentationen, kan du se, at Task.Delay Method-metoden opretter en opgave, der fuldføres efter et angivet antal millisekunder. (Faktisk vil en ny tråd blive oprettet, og der vil blive tilføjet await for at vente på, at opgaven bliver udført, jeg ved ikke, om jeg forstår det korrekt)

Hyperlink-login er synlig.

Derudover er der forskel på Task og void

Opgaven returnerer en asynkron metode, der kan vente
Void return asynkron metode kan ikke vente, den virker asynkront, du kan ikke vide, hvornår den er færdig, du kan ikke overvåge status på den asynkrone operation.


Henvisning:

Hyperlink-login er synlig.
Hyperlink-login er synlig.

Sammenfattende: der er et problem med koden, jeg bør ikke bruge Thread.Sleep inde i Task-metoden
Opslået på 21/07/2020 13.09.29 |
Jeg havde det samme problem i dag, hvor jeg brugte multithreading til AES-kryptering, Task er meget langsommere end Thread!!
Har udlejeren fundet årsagen?
Opslået på 12/10/2020 19.24.48 |
Dette indlæg blev sidst redigeret af tongli1996218 den 2020-10-12 kl. 19:43

Efter at have testet ejerens kode, vil tiden for opgaven fortsætte med at blive kortere, når programmet startes og køres flere gange, og på min computer vil den blive reduceret til mindre end Thread, og Thread er stabil inden for denne tid.

Det blev senere opdaget, at Thread.Sleep(100)-metoden havde en negativ indvirkning på Task, men ikke på Thread, og Thread.Sleep(100) kunne erstattes med anden tidskrævende programverifikation såsom numerisk selvaddition eller afvent Task.Delay(100).

PS: Thread.Sleep vil afslutte den aktuelle tråd-slicing-tid efter kald, for eksempel vil Thread.Sleep(0) afslutte den aktuelle thread-slicing-tid og overføre den til andre tråde for at køre. Inde i opgaven findes en trådpool, som kan optimere kontekstskiftet af tråde og reducere CPU-tabstiden (især for multi-core CPU-optimering), mens Thread.Sleep(100) vil forstyrre switching-logikken i den oprindelige trådpool for opgaven, hvilket forårsager meget CPU-tidstab

Hvis du erstatter Thread.Sleep(100) med await Task.Delay(100), vil du opdage, at opgavens tidsforbrug kun er mere end 100 millisekunder, som vist nedenfor:
privat void TaskTest()
{
        Thread.Sleep(100);
         ... Udfør handlingen
}
Erstattet af
privat asynkron void TaskTest()
{
      afventer Opgave.Forsinkelse(100);
      ... Udførelsen tager mere end 100 millisekunder for opgaven, hvilket svarer til den oprindelige Thread.Sleep(100) for Thread
}




 Udlejer| Opslået på 12/10/2020 22.53.05 |
tongli1996218 Opslået den 2020-10-12 kl. 19:24
Efter at have testet ejerens kode, når programmet startes, vil opgavens tid fortsætte med at falde efter flere kørselsforsøg, og på min computer vil den blive reduceret til mindre end Thread...

Jeg prøvede at ændre det til kode sådan her:
Opgave.Forsinkelse(100000);

Opgaveudførelsestid:14,1306 ms, den samlede tid er faktisk meget kort, men jeg fandt ud af, at metoden, som Task kaldte, ikke fuldførte eksekveringen.
Opslået på 13/10/2020 09.34.33 |
Dette indlæg blev sidst redigeret af tongli1996218 den 2020-10-13 09:40
Udgivet den 2020-10-12 kl. 22:53
Jeg prøvede at ændre det til kode sådan her:
Opgave.Forsinkelse(100000);

For at sikre samme kode som Thread, er min operation følgende kode, og ovenstående er pseudokode
PS: Kald blot await Task.Delay, og tilføj så ingen kode, tråden åbnet af opgaven returneres straks, for at sikre simuleringen af compute-bound, kan du bruge for (int a = 0; a< 1000000; ++a){}; Sådanne metoder anvendes i stedet

privat asynkron statisk void TaskTest()
        {
            afvent Opgave.Forsinkelse(100000);
             Interlocked.Increment (ref run);    lås, men overheaden er mindre
            hvis(kør == j)
             {
                Stopur. Stop(); Stop overvågning
                TimeSpan timespan = stopur. Løb forløbet;  Får den samlede tid målt af den aktuelle instans
                Console.WriteLine("Opgaveudførelsestid:" + tidsrum. TotalMillisekunder); Samlede millisekunder
              }
        Den tid, der bruges, er også meget kort


Ansvarsfraskrivelse:
Al software, programmeringsmaterialer eller artikler udgivet af Code Farmer Network er kun til lærings- og forskningsformål; Ovenstående indhold må ikke bruges til kommercielle eller ulovlige formål, ellers skal brugerne bære alle konsekvenser. Oplysningerne på dette site kommer fra internettet, og ophavsretstvister har intet med dette site at gøre. Du skal slette ovenstående indhold fuldstændigt fra din computer inden for 24 timer efter download. Hvis du kan lide programmet, så understøt venligst ægte software, køb registrering og få bedre ægte tjenester. Hvis der er nogen overtrædelse, bedes du kontakte os via e-mail.

Mail To:help@itsvse.com