Filetați în Delfi este diavolul teribil ca el este pictat


Filetați în Delphi: este diavolul teribil ca el este pictat?

Filetați în Delphi: este diavolul teribil ca el este pictat?

vazut de multe ori pe opinia forumuri că fluxurile nu sunt necesare la toate, orice program poate fi scris astfel încât acesta va funcționa bine fără ele. Desigur, dacă nu faci nimic mai serios „Hello World“ este adevărat, dar dacă câștiga treptat experiență, mai devreme sau mai târziu, orice programator novice odihnit în posibilitatea unui cod „plat“, este necesar să paraleliza sarcini. Unele sarcini nu pot fi realizate la toate fără utilizarea de fire, de exemplu, lucrul cu prize, COM-port, așteptați mult timp pentru orice evenimente, etc.

Toată lumea știe că Windows este un multitasking. Pur și simplu pune, acest lucru înseamnă că mai multe programe pot rula simultan pe sistemul de operare. Tot ce a deschis Task Manager și pentru a vedea o listă de procese. Procesul - o instanță a cererii de rulare. De fapt, de la sine nu funcționează, este creat atunci când aplicația începe, conține informații de proprietate, prin care sistemul este de lucru cu el, așa a făcut el să aloce memoria necesară pentru codul și date. Pentru a face programul să funcționeze, este creat în fluxul. Orice proces conține cel puțin un fir, și este responsabil pentru executarea de cod și obține timpul CPU. Acest lucru este realizat și programele de lucru paralele imaginare, sau cum este numit, un pseudo. De ce este imaginar? Da, pentru că de fapt procesorul la un moment dat poate transporta doar o singură bucată de cod. Ferestre distribuie timp CPU pentru toate firele din sistem, unul câte unul, astfel, se pare că lucrează în același timp. Fluxurile reale care funcționează în paralel, poate fi numai pe mașini cu două sau mai multe procesoare.

Pentru a crea fire suplimentare în Delphi există o TThread clasa de baza. de la ea vom fi moștenită în punerea în aplicare a fluxurilor lor. Pentru a crea un „schelet“ al unei noi clase, puteți selecta meniul File - New - Object Subiect, Delphi va crea un nou modul cu piesa de lucru din clasa sa. Voi descrie pentru prezentarea în modulul de formular. După cum puteți vedea, în această recoltare a adăugat o singură metodă - Executare. Asta e, și avem nevoie pentru a trece peste codul în interiorul acestuia și va funcționa într-un fir separat. Și astfel, să ne scrie un exemplu - a alerga într-un flux de buclă fără sfârșit:

Executați proba pentru a efectua și faceți clic. Se pare că nu se întâmplă nimic - forma nu este atârnat, reacționează la mișcare. De fapt, nu este așa - du-te la Task Manager și veți vedea că procesorul este încărcat în întregime. Acum, în procesul de aplicația care rulează două fire - unul a fost creat inițial, atunci când aplicația pornește. Cea de a doua, care se va livra un procesor - am creat prin simpla apăsare a unui buton. Deci, să vedem, ce face codul în Button1Click:

NewThread: = TNewThread.Create (true); aici am creat un exemplu de TNewThread. Creați un constructor are doar o singură opțiune - CreateSuspended tipul boolean, care indică începe un nou fir imediat după crearea (dacă este fals), sau așteptați comanda (dacă este adevărat). New.FreeOnTerminate: = true; proprietate FreeOnTerminate specifică faptul că fluxul de după sfârșitul automat, obiectul va fi distrus și nu va trebui să-l distrugă manual. În exemplul nostru, nu contează, pentru că, în sine, niciodată nu va fi finalizat, dar vor fi necesare în următoarele exemple. NewThread.Priority: = tpLower; Prioritate proprietate, dacă nu ați ghicit din numele, setează prioritatea firului. Da, da, fiecare fir din sistem are propria prioritate. În cazul în care timpul procesorului nu este suficient, sistemul începe să-l distribuie în funcție de fluxul de prioritate. proprietate prioritară poate lua următoarele valori:
  • tpTimeCritical - critică
  • tpHighest - foarte mare
  • tpHigher - de mare
  • tpNormal - intermediar
  • tpLower - scăzut
  • tpLowest - foarte scăzut
  • tpIdle - rulează flux în timpul sistemului de timp de inactivitate
Scop flux de prioritate ridicată nu este necesară, cu excepția cazului cerut de sarcina, deoarece este o sarcină grea pe sistem. NewThread.Resume; Ei bine, de fapt, fluxul începe.

Cred că acum ați înțeles modul în care sunt create fire. Notă, nimic complicat. Dar nu toate atât de simplu. S-ar părea - scrie orice cod în metoda Execute, și totul, și fără fluxuri au o proprietate neplăcută - ei nu știu nimic despre unul pe altul. Și ce de ea? - Tu întrebi. Iată ce: să spunem că sunt încercarea de a schimba fluxul de alte bunuri ale oricărei componente pe formular. După cum se cunoaște, VCL singură intrare, toate codul în cadrul aplicației este executată secvențial. De exemplu, în procesul de orice schimbat date în cadrul claselor VCL, sistemul selectează în momentul în care fluxul principal trece în jurul valorii de alte fluxuri și se întoarce înapoi, executarea de cod continuă de la punctul în care au stagnat. Dacă suntem de schimbare a fluxului lor ceva, de exemplu, sub formă, este implicat în mai multe mecanisme de VCL (Vă reamintesc de fluxul de bază acum „suspendat“), respectiv, în această perioadă va avea timp să se schimbe date. Dintr-o dată timp este dat la fluxul principal din nou, el continuă liniștit executarea sa, dar datele au schimbat! Pentru ceea ce poate duce - este imposibil de prezis. Puteți verifica o mie de ori și nu se întâmplă nimic, iar pe programul de mii și prima se va prăbuși. Acest lucru este valabil nu numai pentru a interacționa cu fluxul principal și mai mult, dar, de asemenea, la o interacțiune între fluxurile. Scrie un astfel de program nesigur, desigur, este imposibil.

Aici am ajuns la o problemă foarte importantă - sincronizarea firului.

Acum ProgressBar se mișcă, și este complet sigur. Un seif este motivul pentru care: Sincronizarea procedura de la momentul suspendării executării fluxului nostru, și trece controlul la fluxul principal, și anume SetProgress executat în firul principal. Este necesar să ne amintim, deoarece unele fac greșeli, efectuarea în interiorul Sincronizați de lucru pe termen lung, în acest caz, în mod evident, sub forma îngheață pentru o lungă perioadă de timp. Prin urmare, utilizați Sincronizare pentru a afișa informații - aceleași componente antet progresul actualizare dviganie, etc.

Este posibil să fi observat că vom folosi procesul de sleep în ciclul. Într-un singur fir de aplicare Sleep este rar folosit, dar fluxul este foarte comod de utilizat. Exemplu - o buclă fără sfârșit, până când face un fel de condiție. Dacă nu introduceți pentru a dormi incarcam pur și simplu de lucru inutil de sistem.

Sper să înțelegi cum funcționează Sincronizați. Dar există un alt mod destul de ușor de a transfera formularul de informații - trimiterea unui mesaj. Să ne uităm la ea, de asemenea. Pentru a face acest lucru, vom declara o constantă:

Acum avem o mică schimbare, puteți simplifica spune chiar punerea în aplicare a metodei de executare a fluxului nostru:

Folosind funcția SendMessage, vom trimite o fereastra aplicație de mesagerie, dintre care unul conține parametrii pe care doriți să progreseze. Un mesaj este în coada de așteptare, și în conformitate cu această coadă vor fi procesate de către firul principal, în cazul în care metoda este executată SetProgressPos. Dar există un avertisment: SendMessage, așa cum este cazul cu Synchronize, să suspende executarea fluxului nostru, în timp ce firul principal nu procesează mesajul. Dacă utilizați PostMessage acest lucru nu se întâmplă, vom trimite un flux de mesaje și va continua activitatea sa, și numai atunci când este procesat acolo - nu contează. Care dintre aceste funcții pentru a utiliza - vă decideți, totul depinde de sarcina.

Aici, în principiu, am acoperit modalitățile de bază de lucru cu componentele firului VCL. Și dacă programul nostru nu este un fir nou, dar mai multe? Și trebuie să organizăm lucrul cu aceleași date? Aici am ajuns la ajutorul altor metode de sincronizare. Unul dintre ei considerăm. Pentru a-l pune în aplicare, trebuie să adăugați la modulul SyncObjs de proiect.

Modul cel mai interesant, în opinia mea - secțiunile critice

Acestea funcționează după cum urmează: doar un singur fir, cealaltă de așteptare pentru finalizarea acestuia se poate lucra în cadrul unei secțiuni critice. Pentru a înțelege mai bine toate comparațiile sunt realizate cu o țeavă îngustă, imaginați-vă, pe de o parte, fluxurile de „mulțime“, dar conducta poate „urca“ singurul, și atunci când el „trece prin“ - începe a doua mișcare, și așa mai departe, în ordine. Chiar și mai ușor de înțeles acest lucru cu un exemplu, și același ProgressBar'om. Deci, rulați unul din exemplul dat mai devreme. Faceți clic pe butonul, așteptați câteva secunde și apoi apăsați din nou. Ce se întâmplă? ProgressBar a început să sară. Sărituri pentru că noi folosim mai mult de un flux, dar două, și fiecare dintre ele transmite un progres sensuri diferite. Acum, un pic rework codul în forme de evenimente OnCreate va crea o secțiune critică:

Avem două TCriticalSection avem nevoie de o metodă, Enter și încheiați, respectiv, în și în afara ei. Punem codul nostru într-o secțiune critică:

Încercați să executați aplicația și apăsați butonul de mai multe ori, și apoi numărul de câte ori va avea un progres. În mod evident, ceea ce este esența? Prima dată când apăsați butonul, vom crea un flux, este nevoie de o secțiune critică, și începe să lucreze. Împingeți al doilea - al doilea fir este creat, dar secțiunea critică este ocupată, iar el așteaptă până când se eliberează primul. În al treilea rând, a patra - toate trec doar pe coada.

sectiuni critice sunt convenabil utilizate în prelucrarea acelorași date (liste, tablouri) de fire diferite. Prin înțelegerea modului în care acestea funcționează, puteți găsi întotdeauna o utilizare pentru ei.

În acest articol mici nu acoperă toate metodele de sincronizare, există evenimente (TEvent), precum și sistem de obiecte, cum ar fi mutex (Mutex), semafoarele (Semafor), dar ele sunt mai potrivite pentru comunicarea între aplicații. Restul, în ceea ce privește clasa de utilizare TThread, puteți învăța pe cont propriu, în HELP'e toate destul de detaliate. Scopul acestui articol - pentru a arăta începători, nu este atât de greu și înfricoșător lucru să dau seama ce este ceea ce. Și o mulțime de practică - cel mai important lucru este experienta!