Fire de execu ¥£ie iasimin/pw/C6_2006.pdf¢  fir de execu ¥£ie, solu...

download Fire de execu ¥£ie iasimin/pw/C6_2006.pdf¢  fir de execu ¥£ie, solu ¥£ia este de a atribui un timp maxim

If you can't read please download the document

  • date post

    02-Feb-2020
  • Category

    Documents

  • view

    0
  • download

    0

Embed Size (px)

Transcript of Fire de execu ¥£ie iasimin/pw/C6_2006.pdf¢  fir de execu ¥£ie, solu...

  • 1

    Fire de execuţie În acest capitol vom discuta conceptul de fir de execuţie şi vom descrie modul în care sistemul foloseşte fire de execuţie pentru a executa codul aplicaţiei noastre. La fel ca şi procesele, firele au proprităţi asociate lor şi vom discuta despre unele dintre funcţiile disponibile pentru interogarea şi schimbarea acestor proprietăţi. De asemenea vom examina funcţiile care ne permit să creăm să creăm noi fire in sistem. În final vom vorbi despre terminarea frelor de execuţie.

    Când creăm un fir de execuţie

    Un fir de execuţie descrie o cale de execuţie în interiorul unui proces. De fiecare dată când un proces este iniţializat, sistemul creează un fir de execuţie principal. Acest fir porneşte codul C run-time de pornire, care la rândul lui apelează funcţia noastră WinMain, apoi continuă să se execute până când funcţia WinMain returnează şi codul C run-time de pornire apelează ExitProcess. Pentru multe aplicaţii, firul principal de execuţie este singurul fir de execuţie de care are nevoie aplicaţia. Totuşi, procesele pot crea fire suplimentare pentru a le ajuta să îşi îndeplinească sarcinile. Ideea din spatele creării firelor de execuţie este de a utiliza cât mai mult timp de procesor.

    De exemplu, un program care lucrează cu foi de calcul are nevoie să efectueze recalculări pe măsură ce utilizatorul introduce date în celule. Deoarece recalculările unei foi de calcul complexe pot avea de nevoie de câteva secunde pentru a fi efectuate, o aplicaţie bine gândită nu ar trebui să recalculeze foaia de calcul după fiecare schimbare pe care o efectuează utilizatorul. În schimb, recalcularea ar trebui făcută într-un fir de execuţie cu prioritate mai redusă decât firul principal de execuţie. În acest mod, dacă utilizatorul introduce date, firul principal rulează, lucru care înseamnă că sistemul nu va programa nici un timp de calcul firului care efectuează recalcularea. Atunci când utilizatorul se opreşte din scris, firul principal este suspendat, aşteptând o intrare iar firului care face recalcularea îi este dat timp de lucru. De îndată ce utilizatorul începe să scrie din nou, firul principal de execuţie, având prioritate mai mare, trece in faţa firului cu recalcularea. Crearea firelor de execuţie adiţionale face ca aplicaţia să devină „înţelegătoare” cu utilizatorul. De asemenea este destul de uşor de implementat.

    Într-un exemplu similar, putem crea un fir de execuţie suplimentar pentru o funcţie de repaginare într-un procesor de texte care trebuie să repagineze textul pe măsură ce utilizatorul introduce text în document. Microsoft Word pentru Windows, de exemplu, trebuie să simuleze un comportament multifiliar în Windows pe 16 biţi dar poate foarte uşor să creeze un nou fir dedicat repaginării documentului în Win32. Firul principal de execuţie va fi responsabil cu procesarea intrărilor utilizatorului, iar firul din fundal va fi responsabil cu localizarea salturilor la pagină nouă.

    Este de asemenea folositor pentru a crea un fir de execuţie separat pentru a trata tipărirea în cadrul unei aplicaţii. În acest mod, utilizatorul poate continua să folosească aplicaţia în timpul tipăririi. În plus, atunci când efectuăm o operaţie care într-o perioadă mare de timp, multe aplicaţii afişează o căsuţă de dialog care permite utilizatorului să oprească operaţia. De exemplu, atunci când Explorer-ul copie nişte fişiere, afişează o căsuţă de dialog care, în afara faptului că arată progresul operaţiei, de asemenea conţine un buton Cancel. Dacă apăsăm acest buton în timp ce fişierele sunt copiate, oprim operaţia.

  • 2

    În Windows pe 16 biţi, implementarea acestui tip de funcţionalitate are nevoie de apeluri periodice ale funcţiei PeekMessage în interiorul cozii de mesaje a copierii fişierelor. Apelurile PeekMessage pot fi făcute doar între citirea şi scrierea unui fişier. Dacă citim un block mare de date, răspunsul la apăsarea butonului nu apare până când blocul nu este citit. Dacă fişierul este citi de pe o unitate de dischetă, acest lucru poate dura câteva secunde. Deoarece timpul de răspuns este atât de lent, putem apăsa de mai multe ori pe un astfel de buton crezând că sistemul nu ştie că am oprit operaţia.

    Punând copierea fişierului într-un fir de execuţie separat, nu trebuie să împrăştiem apeluri ale funcţiei PeekMessage prin codul nostru – firul nostru operează independent. Acest lucru înseamnă că o apăsare a butonului Cancel are un efect imediat.

    Putem de asemenea să folosim fire de execuţie pentru a crea aplicaţii care simulează evenimente din lumea reală. Un exemplu este o simulare a unui supermarket. Deoarece fiecare cumpărător este reprezentat de propriul fir de execuţie, teoretic fiecare este independent unul de altul şi poate intra în magazin şi poate ieşi oricând crede de cuviinţă. Simularea poate monitoriza aceste activităţi pentru a determina cât de bine funcţionează supermarket-ul.

    Deşi putem rula simulări, există probleme potenţiale. În primul rând, în mod ideal am vrea ca fiecare fir de execuţie să fie executat de către un procesor propriu. Deoarece nu sete o soluţie practică să ne aşteptăm să avem un procesor pentru fiecare fir de execuţie, soluţia este de a atribui un timp maxim după care sistemul să pauzeze execuţia unui fir, permiţând execuţia altuia. De exemplu, dacă simularea noastră are două fire de execuţie şi maşina pe care rulează are 8 procesoare, sistemul poate atribui fiecare fir unui procesor diferit. Totuşi, dacă simularea are 1000 de fire de execuţie, sistemul va trebui să le atribuie continuu câte unul din cele 8 procesoare. Totuşi poate apărea o suprasolicitare atunci când sistemul programează un număr mare de fire pentru un număr redus de procesoare. Dacă aplicaţia noastră are un timp de execuţie mai mare, suprasolicitarea are un impact relativ scăzut asupra simulării. Totuşi, dacă simularea se face într-o perioadă scurtă de timp, suprasarcina poate lua un procent mai mare din timpul total de execuţie al aplicaţiei.

    În al doilea rând, sistemul în sine are nevoie de unele fire de execuţie care să ruleze în timp ce alte procese sunt în execuţie. Toate aceste fire de execuţie trebuie să fie programate pentru timp de procesor la rândul lor, lucru care în mod sigur va afecta rezultatele aplicaţiei.

    Şi în al treilea rând, simularea este folositoare doar dacă păstrăm evidenţa progresului ei. De exemplu, simularea supermarket-ului adaugă intrări într-o listbox pe măsură ce cumpărătorii efectuează diferite acţiuni; adăugarea acestor intrări ia din timpul aplicaţiei. Principiul de Nesiguranţă al lui Heisenberg afirmă ca determinarea mai precisă a unei cantităţi are ca efect calcularea mai precisă a altora. Acest principiu este în mod sigur adevărat în cazul de faţă.

    Când nu trebuie să creeăm un fir de execuţie

    Prima dată când la majoritatea programatorilor le este dat accesul la un mediu care suportă fire de execuţie multiple, ei sunt extaziaţi. Dacă ei ar fi avut firele de execuţie mai devreme, aplicaţiile lor ar fi fost mai uşor de scris. Şi, pentru un motiv necunoscut, aceşti programatori încep divizarea unei aplicaţii în piese individuale, fiecare putând fi executată ca propriul său fir de execuţie. Acesta nu este modul corect de dezvoltare a unei aplicaţii.

  • 3

    Firele sunt incredibil de folositoare şi îşi au locul lor, dar atunci când folosim fire de execuţie putem crea noi potenţiale probleme în timp ce încercăm să rezolvăm pe cele vechi. De exemplu, să spunem că dezvoltăm a aplicaţie care procesează cuvinte si vrem să permitem ca funcţia de tipărire să ruleze ca propriul fir de execuţie. Acest lucru pare o idee bună deoarece utilizatorul poate imediat să se întoarcă la editarea documentului în timp ce acesta este tipărit. Dar totuşi acest lucru înseamnă că datele din document pot fi schimbate în timp ce documentul este tipărit. Acest lucru creează un nou tip de problemă pe care trebuie să o rezolvăm. Totuşi poate ar fi mai bine să nu lăsăm tipărirea în propriul fir de execuţie; dar această „soluţie” este puţin mai drastică. Ce ar fi dacă am permite utilizatorului să editeze un alt document dar să blocăm documentul care trebuie tipărit astfel încât să nu poată fi modificat până când procesul de tipărire nu s-a terminat ? Cea de-a treia soluţie este : copiem fişierul de tipărit într-un fişier temporar şi lăsăm utilizatorul să îl modifice pe cel original. Atunci când fişierul temporar care conţine documentul s-a terminat de tipărit, putem şterge fişierul temporar.

    După cum se observă, firele de execuţie rezolvă unele probleme cu riscul creării altora noi. O altă utilizare greşită a firelor de execuţie poate apărea în dezvoltarea interfeţei utilizator a unei aplicaţii. În majoritatea aplicaţiilor, toate componentele interfeţei utilizator ar trebui să împartă acelaşi fir de execuţie. Dacă creăm o căsuţă de dialog, de exemplu, nu ar avea nici un sens ca un listbox să fie creat de un fir de execuţie şi un buton de alt fir.

    Să mergem puţin mai departe şi să spunem că avem propriul control listbox care sortează datele de fiecare dată este adăugat sau şters un element. Operaţia de sortare poate dura câteva secunde, aşa că decidem să îi atribuim acestui control un fir de execuţie propriu. În acest mod, ut