Model de flux

Aplicația Windows Presentation Foundation (WPF) este concepută pentru a ajuta dezvoltatorii să evite dificultățile în dezvoltarea firelor. Ca rezultat, majoritatea dezvoltatorilor WPF nu trebuie să scrie o interfață care utilizează mai multe fire. Deoarece programele cu mai multe fire sunt complexe și greu de depanat, acestea ar trebui evitate dacă există soluții cu un singur filet.







Indiferent de calitatea arhitecturii, nici o platformă UI nu poate oferi o soluție cu un singur file pentru fiecare tip de sarcină. WPF sa apropiat destul de mult de această problemă, însă există încă situații în care mai multe fire îmbunătățesc performanța interfeței cu utilizatorul (UI) sau performanța aplicațiilor. După discutarea unora dintre principalele materiale din această lucrare, aceste situații sunt luate în considerare și în final sunt discutate câteva informații mai detaliate.

Această secțiune conține următoarele secțiuni.

Dezvoltarea aplicațiilor WPF începe, de obicei, cu două fire: una pentru procesarea redării, iar cealaltă pentru gestionarea interfeței UI. Fluxul de vizualizare este realizat eficient invizibil utilizatorului în fundal, în timp ce fluxul UI primește date de intrare, procesează evenimente, afișează imaginea pe ecran și execută codul aplicației. Cele mai multe aplicații utilizează un singur fir UI, deși în unele cazuri este mai bine să utilizați mai multe. Mai târziu, aceasta va fi considerată ca un exemplu.

Fire thread-ul UI cozi lucruri de lucru în interiorul unui obiect numit Dispecer. Obiectul Dispatcher selectează articolele de lucru în funcție de priorități și execută fiecare până la finalizare. Fiecare flux UI trebuie să aibă cel puțin un obiect Dispatcher. și fiecare obiect Dispatcher poate realiza articole de lucru într-un singur fir.

Condiția necesară pentru crearea unor aplicații receptive și ușor de utilizat este creșterea maximă a performanței Dispatcherului. mențineți obiectele de lucru mici. Cu această metodă, elementele nu mai rămân învechite în coada Dispatcherului în așteptarea procesării. Orice întârziere între datele de intrare și răspunsurile poate fi frustrant pentru utilizator.

Cum ar trebui aplicațiile WPF să se ocupe de operațiuni mari în acest caz? Ce se întâmplă dacă codul include calcule mari sau necesită o interogare de bază de date pe serverul de la distanță? În mod obișnuit, operațiile mari sunt procesate într-un fir separat, lăsând firul UI liber să servească elemente din coada Dispatcher. După ce ați terminat o operație mare, acesta poate trece rezultatul înapoi la fluxul UI pentru afișare.

Din punct de vedere istoric, sistemul de operare Windows permite accesul la elementele UI numai la firul care le-a creat. Acest lucru înseamnă că firul de fundal responsabil pentru o sarcină pe termen lung nu poate actualiza câmpul text când acesta se termină. Windows creează această constrângere pentru a asigura integritatea componentelor UI. Lista poate părea ciudată dacă conținutul acesteia este actualizat de firul de fundal în timpul procesului de afișare.

WPF sprijină mecanismul integrat de excludere reciprocă, care realizează această coordonare. Cele mai multe clase dintr-o aplicație WPF sunt derivate din clasa DispatcherObject. Când creați un DispatcherObject, acesta stochează o referință la obiectul Dispatcher. asociate cu firul curent aflat în desfășurare. De fapt, DispatcherObject este asociat cu firul care la creat. În timpul execuției, DispatcherObject poate apela metoda VerifyAccess publică. VerifyAccess verifică obiectul Dispatcher. asociat cu firul curent și îl compară cu o trimitere la Dispatcher. care este salvat în timpul creației. Dacă nu se potrivesc, metoda VerifyAccess aruncă o excepție. VerifyAccess se intenționează să fie apelat la începutul fiecărei metode care aparține DispatcherObject.

Dacă un singur fir poate modifica interfața utilizator, cum interacționează firele de fundal cu utilizatorul? Un fir de fundal poate cere firului UI să efectueze o operațiune în numele său. Aceasta face acest lucru prin înregistrarea unui obiect de lucru în obiectul Dispecer UI. Clasa Dispatcher oferă două metode pentru înregistrarea articolelor de lucru: Invocate și BeginInvoke. Ambele metode atribuie unui delegat execuție. Metoda Invoke este un apel sincron - nu returnează o valoare până când firul UI nu finalizează execuția delegatului. Metoda BeginInvoke este asincronă și returnează imediat o valoare.







Obiectul Dispatcher aranjează elementele din coada lor prioritară. Există zece nivele care pot fi specificate atunci când un element este adăugat în coada Dispatcher. Aceste priorități sunt stocate în enumerarea DispatcherPriority. Pentru informații detaliate despre nivelele DispatcherPriority, consultați documentația Windows SDK.

Exemplu de aplicație cu un singur file, cu o lungă execuție a calculelor

Cele mai multe interfețe grafice de utilizator (GUI) petrec cea mai mare parte a timpului lor în așteptare pentru evenimentele care sunt create ca răspuns la acțiunile utilizatorului. Cu o programare atentă, acest timp de inactivitate poate fi folosit constructiv, fără a scădea viteza răspunsului UI. Modelul de flux WPF nu permite intrarea pentru a întrerupe operațiunea care apare în fluxul UI. Aceasta înseamnă că trebuie să reveniți periodic la obiectul Dispatcher. Pentru a procesa evenimentele de intrare amânate înainte de a deveni caduce.

Luați în considerare următorul exemplu:

Model de flux

Această aplicație simplă caută numere simple începând de la trei ani. Când utilizatorul apasă butonul Start, căutarea începe. Când programul găsește un număr prime, actualizează interfața de utilizator. În orice moment, utilizatorul poate opri căutarea.

Cu toată simplitatea operării, căutarea numerelor prime poate să apară infinit, ceea ce reprezintă unele dificultăți. Dacă s-a efectuat procesarea tuturor operațiilor de căutare în interiorul butonului de selectare a clicurilor pe buton, fișierul UI nu ar fi fost capabil să facă față altor evenimente. UI nu a putut răspunde la datele de intrare sau nu a procesat mesajele. Nu va actualiza afișajul și nu va răspunde la un clic pe buton.

Puteți căuta un număr prime într-un fir separat, dar atunci ar trebui să rezolvați problemele de sincronizare. Folosind o abordare cu un singur filet, puteți actualiza direct semnătura, care listează cel mai mare număr prime.

Dacă împărțiți sarcina de calcul în fragmente gestionate, puteți reveni periodic la obiectul Dispatcher și la procesele de procesare. Puteți oferi aplicației WPF posibilitatea de a actualiza și procesa intrarea.

Cea mai bună modalitate de a împărți timpul de procesare între procesarea și procesarea unui eveniment este de a gestiona calculul de la obiectul Dispatcher. Cu metoda BeginInvoke, aveți posibilitatea să programați o verificare a unui număr prime în aceeași coadă pe care provin evenimentele UI. În acest exemplu, se planifică să se verifice numai un număr prime la un moment dat. După ce verificarea primei cifre este finalizată, următorul control este planificat imediat. Această verificare se efectuează numai după procesarea evenimentelor UI în așteptare.

Model de flux

Cu acest mecanism, Microsoft Word rulează un verificator de ortografie. Ortografia este efectuată în fundal, utilizând timpul de așteptare al firului UI. Să ne uităm la cod.

Următorul exemplu prezintă codul XAML care creează interfața de utilizator.

Această metodă verifică dacă următorul număr impar este simplu. Dacă este simplu, metoda actualizează direct blocul de text bigPrime. pentru a reflecta rezultatul căutării. Putem face acest lucru deoarece calculul are loc în același fir care a fost utilizat pentru a crea componenta. Dacă utilizați un fir separat pentru calcule, va trebui să aplicați un mecanism mai sincronizat de sincronizare și să efectuați actualizări în firul UI. Această situație va fi demonstrată mai târziu.

Pentru un exemplar complet de cod sursă, consultați secțiunea Single-Threaded Application with Sequence of Calculation Running Long.

Procesează o operație de blocare cu un fir de fundal

Operațiunile de blocare a proceselor într-o aplicație grafică pot fi o sarcină dificilă. Nu vom apela metode de blocare de la manipulatorii de evenimente, deoarece aplicația va fi oprită. Puteți utiliza un fir separat pentru a gestiona aceste operații, dar apoi trebuie să vă sincronizați cu fluxul UI, deoarece nu puteți schimba direct GUI din fluxul de lucru. Puteți introduce delegați în obiectul Dispatcher din fluxul UI utilizând metoda Invoke sau BeginInvoke. Ca rezultat, acești delegați vor fi executați cu permisiunea de a schimba elementele UI.

În acest exemplu, simulăm un apel de la distanță care primește o prognoză meteo. Utilizăm un flux de lucru separat pentru a efectua acest apel și pentru a planifica o metodă de actualizare a fluxului UI în obiectul Dispatcher atunci când acesta termină.

Model de flux







Articole similare

Trimiteți-le prietenilor: