Când nu ar trebui să folosesc ThreadPool în .Net?

Când trebuie să nu să utilizez ThreadPool în .Net?

Se pare că cea mai bună opțiune este utilizarea unui ThreadPool, caz în care, de ce nu este singura opțiune?

Care sunt experiențele dvs. în acest sens?

0
fr hi bn

9 răspunsuri

The only reason why I wouldn't use the ThreadPool for cheap multithreading is if I need to…

  1. interractați cu metoda care rulează (de exemplu, să o omoare)
  2. executați un cod pe un thread STA (acest lucru mi sa întâmplat)
  3. păstrați thread-ul în viață după ce cererea mea a murit (firele ThreadPool sunt fire de fundal)
  4. în cazul în care trebuie să modific prioritatea fișierului. Nu putem schimba prioritatea thread-urilor în ThreadPool, care este implicit Normal.

PS: articolul MSDN " Pool Pool Thread " conține o secțiune intitulată " Când nu se utilizează Thread Pool Threads " o listă foarte asemănătoare, dar puțin mai completă, a posibilelor motive pentru care nu se folosește piscina de fire.

Există o mulțime de motive pentru care ar trebui să săriți ThreadPool , dar dacă nu le cunoașteți, atunci ThreadPool ar trebui să fie suficient de bun pentru dvs.

Alternativ, uita-te la noul Cadrul de Extensii Paralele , care are unele chestii îngrijite care pot fi potrivite nevoilor dvs. fără a fi nevoie să utilizați ThreadPool .

0
adăugat
@Mou: Eu spun că nu am nici o idee despre ceea ce încercați să spuneți, din păcate.
adăugat autor Will, sursa
Dacă citiți acest lucru, atunci ar trebui să utilizați Sarcini în loc de ThreadPool acum.
adăugat autor Will, sursa
adăugat autor Will, sursa
u a spus: - pastreaza thread-ul in viata dupa ce cererea mea a murit (thread-urile ThreadPool sunt fire de fundal) dar cat de departe stiu firul de fundal intotdeauna se termina cu firul principal. deci ce spune u?
adăugat autor Mou, sursa
u a spus păstrează thread-ul în viață după ce cererea mea a murit (thread-urile ThreadPool sunt fire de fundal) ... am dreptate. este adevarat ? dacă firul thread thread este un fir de fond atunci firul poate rula atunci când firul principal a murit? explică plzz
adăugat autor Mou, sursa
Am rulat problemele # 1 (adăugând suportul CancellationToken la o convorbire de lungă durată (5+ minute) "pură" (suficientă) într-o bibliotecă terță parte) și # 2 (redare concurentă wpf ImageSource ... fiecare concurent randamentul trebuie sa inceapa si sa se termine pe acelasi thread STA, dar apoi poate fi inghetat pentru a fi afisat din alte fire) in aceeasi aplicatie, deci acesta este raspunsul potrivit pentru mine. De cele mai multe ori, piscina administrată (sau unul dintre celelalte lucruri, cum ar fi TPL care o utilizează în cele din urmă) este corectă, dar uneori răspunsul corect este
adăugat autor Joe Amenta, sursa

Când veți efectua o operațiune care va dura mult timp sau poate un fir de fond continuu. Cred că ați putea întotdeauna să împingeți cantitatea de fire disponibile în piscină, dar nu ar exista prea puține puncte în a suporta costurile de gestionare a unui fir care nu va mai fi dat înapoi la piscină.

0
adăugat

Pistolele cu filet au sens ori de câte ori aveți conceptul de fire de lucru. Orice moment în care poți transforma cu ușurință procesarea partițiilor în locuri de muncă mai mici, fiecare dintre ele putând fi procesată independent, firele lucrătorilor (și, prin urmare, un pool de fire) au sens.

Piesele de filete nu au sens atunci când aveți nevoie de fir care realizează acțiuni complet diferite și care nu au legătură, care nu pot fi considerate "locuri de muncă"; de exemplu, un fir pentru gestionarea evenimentelor GUI, altul pentru procesarea backend-urilor. Bazele filetelor nu au sens, de asemenea, atunci când procesarea formează o conductă.

Practic, dacă aveți thread-uri care încep, procesează un loc de muncă și abandonează, este probabil un mod de a merge. În caz contrar, fondul de fire nu va ajuta cu adevărat.

0
adăugat
Puteți explica remarca că "filele de fire nu au sens atunci când procesarea formează o conductă"? Să presupunem că am elemente de lucru care trebuie comprimate, apoi criptate, iar comprimarea folosește 10x calculul ca criptare. De ce să nu folosiți un filet cu un raport compresor 10: 1 la firele de criptare?
adăugat autor Cheeso, sursa
Bazele de file sunt, în general, pentru atunci când un program are niște piese de lucru independente și discrete. Dacă există comunicare între firele lucrătorilor (cum ar fi într-o conductă), atunci nu aveți într-adevăr un scenariu de piscină.
adăugat autor Derek Park, sursa

@ Eric, trebuie să fiu de acord cu Dean. Firele sunt scumpe. Nu puteți presupune că programul dvs. este singurul care rulează. Când toți sunt lacomi cu resurse, problema se înmulțește.

Prefer să-mi creez manual firele și să le controlez singur. Păstrează codul foarte ușor de înțeles.

E bine când e potrivit. Dacă aveți nevoie de o mulțime de fire de lucru, totuși, tot ce ați făcut este să vă complicați codul. Acum trebuie să scrieți un cod pentru a le gestiona. Dacă tocmai ați folosit un filet de fișiere, ați obține gratuit tot managementul firului. Și piscina de fire furnizată de limbă este foarte probabil să fie mai robustă, mai eficientă și mai puțin sigură decât orice vă rog pentru tine.

  Thread t = Thread nou (nou ThreadStart (DoSomething));
t.Start ();
t.Join ();
 

Sper că în mod normal veți avea un cod suplimentar între Start() și Join() . În caz contrar, firul suplimentar este inutil și pierzi resursele fără niciun motiv.

Oamenii sunt prea frică de resursele folosite de fire. N-am văzut niciodată crearea și pornirea unui fir care să dureze mai mult de o milisecundă. Nu există o limită grea pentru numărul de fire pe care le puteți crea. Utilizarea RAM este minimă. Odată ce aveți câteva sute de fire, CPU-ul devine o problemă datorită comutărilor de context, deci la acel moment s-ar putea să doriți să obțineți fantezie cu designul dvs.

O milisecundă este un timp lung pe hardware-ul modern. Sunt 3 milioane de cicluri pe o mașină 3GHz. Și din nou, nu ești singurul care creează fire. Firele dvs. concurează pentru CPU împreună cu firele de la celelalte programe. Dacă utilizați nu prea multe fire, și la fel și un alt program, atunci împreună ați folosit prea multe fire.

Serios, nu face viața mai complexă decât trebuie. Nu utilizați rezervorul cu fir dacă nu aveți nevoie de ceva foarte specific pe care îl oferă.

Intr-adevar. Nu face viața mai complexă. Dacă programul dvs. necesită mai multe fire de lucru, nu reinventați roata. Utilizați rezervorul de fire. De aceea este acolo. V-ați rula propria clasă de șir?

0
adăugat
E destul de bine un răspuns. Dar 22 de susținători, în acest moment? Nu este asta bun. Nu există o alegare imensă care să fie terminată din Redmond, nu-i așa?
adăugat autor Will, sursa
@DerekPark: Și nu ar trebui. Am venit aici din cauza unui steag NAA. Apoi, dintr-o gelozie arzătoare, a lăsat comentariul. Doar glume.
adăugat autor Will, sursa
@ Va fi un comentariu de 4 ani. Este o medie de mai puțin de o jumătate de creștere pe lună. Aproape un nivel de vot incredibil.
adăugat autor Derek Park, sursa
@ hwiechers, este jumătate de răspuns, jumătate de răspuns. Așa că nu au avut comentarii când a fost postat și nu sunt dispus să pierd timpul necesar pentru a trece prin toate răspunsurile mele vechi și pentru a le transforma în comentarii.
adăugat autor Derek Park, sursa
@ Va, nu vă faceți griji. Știam că glumești cu privire la alegeri (am reușit să reușim mai bine decât 22 de voturi în 4 ani), dar nu știam cât de serioși ați fost despre comentariul "Nu este bun". :)
adăugat autor Derek Park, sursa
Ideea că nu ar trebui să presupunem codul este singurul lucru care rulează este IMHO un argument împotriva folosind fire thread thread pentru orice număr semnificativ de operații care sunt de așteptat să dureze mai mult de 10ms sau cam asa ceva. Dacă performanța unei părți a unei aplicații depinde de executarea rapidă a apelurilor de completare de intrare/ieșire, dacă o altă parte a aplicației umple coada de corespondență cu metode de lungă durată poate degrada performanța primei părți mult mai mult decât ar avea a doua parte utilizează fire discrete, mai ales dacă aceste metode petre
adăugat autor supercat, sursa
Unii oameni își rostogolește propriul ambalaj peste o serie de caractere și o folosesc ca un șir .. deci este posibil ... și este și trist.
adăugat autor Andrei Rînea, sursa
Eu am votat acest lucru. Acest lucru nu este un răspuns; este un răspuns la altcineva.
adăugat autor hwiechers, sursa

@Eric

@Derek, nu sunt de acord cu scenariul pe care îl folosiți ca exemplu. Dacă nu știți exact ce rulează pe mașină și exact câte fire, mânere, timp CPU, RAM etc., pe care aplicația dvs. le va utiliza sub o anumită încărcare, aveți probleme.

Sunteți singurul client vizat pentru programele pe care le scrieți? Dacă nu, nu poți fi sigură de cele mai multe. În general, nu aveți nicio idee atunci când scrieți un program dacă se va executa în mod eficient în mod solo sau dacă va rula pe un server web care este lovit de un atac DDOS. Nu puteți ști cât timp CPU aveți la dispoziție.

Presupunând că schimbările de comportament ale programului dvs. se bazează pe intrare, este rar să știi exact cât de multă memorie sau timp CPU consumă programul tău. Sigur, ar trebui să aveți o idee destul de bună despre modul în care se va comporta programul dvs., dar majoritatea programelor nu sunt analizate pentru a determina cât de multă memorie, câte mânere etc. vor fi folosite, deoarece o analiză completă este costisitoare. Dacă nu scrieți software în timp real, câștigul nu merită efortul.

În general, pretinzând că știi exact cum se va comporta programul tău este cu totul altminteri, și pretind că știi că totul despre mașină se apropie de absurd.

Și pentru a fi sincer, dacă nu știi exact ce metodă ar trebui să folosești: filete manuale, pile de filete, delegați și cum să le implementezi pentru a face exact ceea ce cererea ta are nevoie, ai probleme. >

Nu sunt total dezacord, dar nu înțeleg cum este relevant. Acest site este aici în mod special, deoarece programatorii nu au întotdeauna toate răspunsurile.

Dacă cererea dvs. este suficient de complexă pentru a solicita reducerea numărului de fire pe care le utilizați, nu veți dori aproape mai mult control mai mult decât ceea ce vă oferă cadrul?

Nu. Dacă am nevoie de un pool de fire, o să folosesc pe cea furnizată, dacă și până nu voi găsi că nu este suficient. Nu voi presupune pur și simplu că fondurile de fire furnizate sunt insuficiente pentru nevoile mele, fără a confirma acest lucru.

Nu vorbesc aici ca pe cineva care are doar cunoștințe teoretice. Scriu și mențin aplicații cu volum mare care folosesc greu multithreading-ul și, în general, nu găsesc piscul firului pentru a fi răspunsul corect.

Cea mai mare parte a experienței mele profesionale a fost cu programe de multithreading și multiprocesare. De multe ori am avut nevoie să îmi rog și propria soluție. Asta nu înseamnă că fondul de fire nu este util sau potrivit în multe cazuri. Piscul filetelor este construit pentru a gestiona firele lucrătorilor. În cazul în care firele multiple ale lucrătorilor sunt adecvate, grupul de fire furnizat ar trebui, în general, să fie prima abordare.

0
adăugat

Nu vorbesc ca pe cineva cu numai   cunoștințe teoretice de aici. eu scriu   și să mențină aplicații cu volum mare   care folosesc greu multithreading,   și în general nu găsesc firul   pool pentru a fi răspunsul corect.

Ah, argumentul de la autoritate - dar întotdeauna să fii în căutarea unor oameni care ar putea fi în echipa de nucleu Windows.

Nici unul dintre noi nu a argumentat cu faptul că, dacă aveți anumite cerințe specifice, atunci .NET ThreadPool ar putea să nu fie ceea ce trebuie. Ceea ce ne opunem este trivializarea costurilor mașinii de a crea un fir.

Cheltuielile semnificative de a crea un fir la raison d'etre pentru ThreadPool în primul rând. Nu vreau ca mașinile mele să fie umplute cu codul scris de persoane care au fost dezinformate cu privire la cheltuiala de a crea un fir și, de exemplu, nu știu că face ca o metodă să fie numită în fiecare DLL care este (unele dintre ele vor fi create de terțe părți) și care ar putea să se încălzească o încărcătură de cod care nu trebuie să fie deloc în RAM și aproape sigur nu trebuie să fie în L1.

Forma ierarhiei de memorie într-o mașină modernă înseamnă că "distragerea" unui CPU este despre cel mai rău lucru pe care îl puteți face și oricine îi pasă de ambarcațiunile sale ar trebui să depună eforturi mari pentru a evita acest lucru.

0
adăugat

Firele Threadpool sunt potrivite pentru sarcini care îndeplinesc ambele criterii:

  1. The task will not have to spend any significant time waiting for something to happen
  2. Anything that's waiting for the task to finish will likely be waiting for many tasks to finish, so its scheduling priority isn't apt to affect things much.

Folosind un thread threadpool în loc să creați unul nou, veți economisi o perioadă semnificativă dar limitată. Dacă acest timp este semnificativ în comparație cu timpul necesar pentru a îndeplini o sarcină, este probabil probabil ca o sarcină threadpool să fie potrivită. Cu cât este mai mare timpul necesar pentru a îndeplini o sarcină, cu atât este mai mică beneficiul folosirii filetului și cu atât este mai mare probabilitatea ca sarcina să împiedice eficiența filetului.

0
adăugat

Pentru a răspunde certurilor, aș adăuga că este mai bine să nu folosiți un thread ThreadPool dacă aveți nevoie să vă asigurați că firul dvs. va începe să funcționeze imediat. Numărul maxim de thread-uri care rulează pe fir este limitat pentru fiecare aplicație, astfel încât este posibil ca piesa de lucru să fie așteptată dacă toți sunt ocupați. Se numește "element de lucru pentru utilizator în coadă", la urma urmei.

Două avertismente, desigur:

  1. Aveți posibilitatea să modificați numărul maxim de thread-uri combinate în cod, la timpul de execuție, astfel încât nimic nu vă oprește verificarea numărului curent față de numărul maxim și ridicarea maximului dacă este necesar.
  2. Spinning-ul unui fir nou vine cu pedeapsa proprie - fie că merită să luați lovitura depinde de circumstanțele dvs.
0
adăugat

MSDN conține câteva motive aici:

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

There are several scenarios in which it is appropriate to create and manage your own threads instead of using thread pool threads:

  • You require a foreground thread.
  • You require a thread to have a particular priority.
  • You have tasks that cause the thread to block for long periods of time. The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting.
  • You need to place threads into a single-threaded apartment. All ThreadPool threads are in the multithreaded apartment.
  • You need to have a stable identity associated with the thread, or to dedicate a thread to a task.
0
adăugat