Články

Tisk článku Tisk článku

Architektura WPF – Dispatcher

[Zpět na kategorii]

Datum: 26. 1. 2012 9:39       Autor: Tomáš Jecha       Zobrazeno: 677x

Kategorie: Aplikace

Seriál: Windows Presentation Foundation (WPF) - Díl 2.

Znát alespoň obrysy toho, jak funguje unvitř technologie, kterou využíváme je nezbytná nutnost. A právě nižší architektuře WPF se věnuje tento článek - konkrétně objektu Dispatcher.


Úvod

V předchozím díle jsem se věnoval WPF jen velmi obecně. Tento článek má za úkol představit objektovou architekturu této technologie, jejíž znalost je nezbytným základem pro pochopení všech hlubších principů.

Dispatcher

K čemu Dispatcher slouží?

Dispatcher je hnacím motorem celého WPF. Jedná se o komponentu, která je principiálně poměrně jednoduchá. Ve zkratce je to fronta úkolů zajišťující, že se úkoly vykonávají po sobě v rámci jednoho hlavního vlákna.

Obecně k uživatelskému prostředí v systému Windows zpravidla přistupujeme vždy z jednoho vlákna. Takové vlákno se nazývá “hlavní vlákno UI” (UI = user interface = uživatelského prostředí). A právě vše, co se v tomto hlavním vlákně bude vykonávat řídí onen Dispatcher. Takový přístup nazýváme single-treaded (jedno-vláknový). Je zde jak z historického hlediska, tak z hlediska čistě praktického.

Díky tomuto single-threaded modelu se nemusíme starat o celou řadu synchronizačních problémů. Pokud chceme, aby se v rámci uživatelského prostředí cokoliv stalo, přidáme úkol do Dispatcheru a on sám zajistí jeho spuštění v hlavním vlákně UI a ve správný čas. Máme tak jistotu, že se nebudou nikdy vykonávat dva úkoly týkající se uživatelského prostředí současně. Mezi tyto operace patří hlavně:

  • vykreslování
  • události uživatelského vstupu (kliknutí na tlačítko, stisk klávesy atp.)
  • změny vlastností (změna textu nadpisu okna, přidání položky do seznamu)
  • a obecně cokoliv, co předáme Dispatcheru do fronty událostí

Výhodou je, že o Dispatcheru nemusíte vůbec vědět, pokud ho nepotřebujete. Je to vnitřní princip WPF a vás v zásadě nemusí zajímat, že kliknutí na tlačítko znamená, že systém Windows pošle událost, která se přeloží na kliknutí a přidá do fronty Dispatcheru. Ten ji, hned jak to bude možné, vyvolá. Zjistí se, na který prvek uživatel kliknul a vyvolá jeho událost. My totiž pohodlně uvnitř této událost vykonáme potřebný kód a opět nás příliš nezajímá, že po jeho dokončení se Dispatcher opět ujme kontroly nad vláknem a čeká na další úkoly, popřípadě vykoná úkoly, které se mezitím nashromáždily.

“Vytuhnutí” single-threaded aplikací

První nevýhodu, na kterou narazíme (nebo spíš důsledek špatného použití) je stav, kdy některá operace v Dispatcheru bude trvat příliš dlouho dobu. V takovém případě celé uživatelské prostředí na dobu provádění operace lidově řečeno “vytuhne”. Dispatcher totiž bude s ostatními úkoly čekat na dokončení blokujícího úkolu. Například událost po stisknutí tlačítka na formuláři bude trvat 10 vteřin. A v tomto čase před dokončením neproběhne žádná událost reagující na vstup od uživatele, ani se žádným způsobem uživatelské prostředí nepřekreslí. Aplikace je tedy po tuto dobu “mrtvá”. Po dokončení operace se opět začnou provádět všechny čekající události a aplikace je opět ovladatelná. Pro uživatele je ale tento stav nepříjemný.

Základní princip aplikací, které reagují na vstupy od uživatelů i v průběhu těchto úkolů je vytvořit samostatné vlákno. Zde je ale důležité podotknout, že z toho samostatného vlákna nemůžeme ovládat uživatelské prostředí. Pokud to uděláme, příkaz skončí s chybou. Je to bezpečnostní mechanismus, který se má zabránit, aby do uživatelského prostředí zasáhlo jiné, než hlavní vlákno UI.

Pokud tedy chceme, aby výsledek operace (který ovlivní nějakým způsobem uživatelské prostředí) proběhl tak, jak je zamýšleno v single-threaded modelu, musíme tento úkol nechat provést právě hlavním vláknem UI. A to tak, že ji z pomocného vláka zaúkolovaného k vykonání dlouhé operace přidáme do úkolů Dispatcheru. Ten se o spuštění v hlavním vlákně postará.

Když tedy použití Dispatcheru shrnu, je důležité, aby operace, které se vykonávají v rámci hlavního vlákna netrvaly příliš dlouho. Po dobu trvání totiž aplikace nebude reagovat.

Životní cyklus Dispatcheru

Typicky je v každé WPF aplikaci jediná instance Dispatcheru. Ta se vytvoří při startu aplikace a stará se o běh hlavního vlákna. Dispatcher je zároveň také nositel informace o tom, zda se má aplikace ukončit. V tom případě opustí smyčku čekání na další úkoly a hlavní vlákno UI se ukončí a s tím i celá aplikace.

DispatcherObject

Téměř každý objekt ve WPF, se kterým chceme pracovat jen z hlavního UI vlákna dědí z třídy DispatcherObject. Ten slouží primárně ke dvou účelům:

  • Vlastnost dispatcherObject.Dispatcher - nese informaci, který Dispatcher se o tento objekt stará
  • Metoda dispatcherObject.CheckAccess – metoda vrací true, pokud ji voláme z vlákna o které se stará příslušný Dispatcher
  • Metoda a dispatcherObject.VerifyAccess - metoda, které vyvolá výjimku, pokud jsme v jiném vlákně, než v tom, o které se stará příslušný Dispatcher

Všechny grafické komponenty bez výjimky ve WPF dědí právě z třídy DispatcherObject. Zároveň je pravidlem, že většina jejich metod a vlastností volá metodu VerifyAccess. Tím se zajistí, že vznikne výjimka, pokud přistoupíme k metodám nebo vlastnostem těchto komponent z jiného, než hlavního vlákna UI.

Závěr

Doufám, že vás trochu kratší, teoretický úvod příliš neodradil. Věřím, že je to však důležitý základ, který pomůže objasnit fungování vašich WPF aplikací. V následujícím díle se vrátíme k návrhu uživatelského prostředí – jazyka XAML.


> Na začátek

 

Hodnocení:

Hlasů: 10
Zvolte své hodnocení

Tomáš Jecha

Tomáš Jecha již několikátým rokem získal ocenění Microsoft MVP. V současné době pracuje ve společnosti AVAST jako architekt a vývojář interních systémů. Působí také jako lektor a konzultant v počítačové škole Gopas. V současné době se zajímá především o SQL Server a technologie nad .NET Frameworkem 4. Společně s Tomášem Hercegem napsal tento web a stará se o jeho administraci.

Podpořte vznik dalších článků

Související články

DílNázev článku 
Díl 1. Úvod do Windows Presentation Foundation (WPF) 19. 1. 2012
Díl 2. Architektura WPF – Dispatcher 26. 1. 2012
Díl 3. Jazyk XAML 2. 2. 2012
Díl 4. Architektura a objektový model WPF 9. 2. 2012
Díl 5. Device independent pixels 16. 2. 2012

RSS Feed RSS Feed

Diskuse

Terminologie

Datum: 27.1.2012 18:50
Autor: Ondřej Linhart
Hodnocení autora: 1208
Příspěvků: 2459
Toto je poprvé (resp. podruhé s předchozím dílem) co čtu, že se někdo o uživatelském rozhraní vyjadřuje jako o uživatelském prostředí. Je to samozřejmě více méně jedno, ale ctím zažitou a obecně používanou terminologii.

Článek se mi líbí, jen škoda že nebyla uvedena jednoduchá ukázka použití Dispatcheru pro přidání úlohy do fronty (ne že bych na to nepřišel sám, kdybych to náhodou potřeboval). Něco jako ve Windows Forms:

WindowsFormsSynchronizationContext.Current.Post( _
New SendOrPostCallback(AddressOf DoWork), _
EventArgs.Empty)

Sub DoWork()
End Sub
 
 
           [Odpovědět]
 
Hodnocení: 1 Čekejte, prosím...

Re: Terminologie

Datum: 27.1.2012 19:26
Autor: Tomáš Jecha
Hodnocení autora: 704
Příspěvků: 1308
Ve Windows Forms, WPF i jiné technologii je to zcela identické. Použije se System.Threading.SynchronizationContext.Current
Funkčně je to zcela identická vlastnost jako to, co jste uvedl, protože jako synchronizační kontext WPF naplní svůj DispatcherSynchronizationContext (poskytuje ho Dispatcher) a Windows Forms zase uvedený WindowsFormsSynchronizationContext. Takže je jedno, jestli jste ve WinForms nebo WPF. Například proto lze používat BackgroundWorker ve všech technologiích stejně.

Volání dispatcheru se ale budu věnovat v samostatném díle. Je to protože lze volit i priorita úloh, což může být v některých případech důležité a to bych rád probral.

A ano, terminologicky se používá více uživatelské rozhraní, to je určitě pravda. V tomhle případě ale nevěřím, že by to někoho mohlo zmást.
 
           [Odpovědět]
 
Hodnocení: 4 Čekejte, prosím...
 

VBNET.CZ | © 2007 Tomáš Herceg, Tomáš Jecha | Kopírování a přejímání jakéhokoliv obsahu z tohoto webu je bez písemného svolení autorů zakázáno.