Wstęp, czyli odwieczny problem pobierania danych
Chyba każdy programista, tworzył kiedykolwiek aplikację, której
jednym z zadań było pobieranie danych ze źródła danych. Ta
popularna i prosta z pozoru czynność, zwykle wygląda następująco
– wysyłamy żądanie o porcję danych, następnie czekamy na
odpowiedź i odbieramy danych. Takie podejście może się jednak
wiązać z pewnymi problemami, z którymi należy się zmierzyć.
Wśród ważniejszych wymienić należy sytuację, gdy po wysłaniu
żądania, żadne dane nie zostaną odesłane lub odesłane zostaną
po nieakceptowalnym dla nas czasie.
Wyobraźmy sobie sytuację (która została przedstawiona na
poniższym rysunku), w której aplikacja po naciśnięciu przycisku
wysyła żądanie o dane do odległej bazy danych, która znajduje
się w chmurze obliczeniowej. Gdy dane zostaną odesłane natychmiast
być może użytkownik nie zauważy niczego niepokojącego. Co jednak
w przypadku, gdyby dane nie zostały odesłane lub czas, po którym
zostały odebrane, przekroczyłby czas wyznaczony przez cierpliwość
użytkownika? Zwykle aplikacja zdawałaby się nie działać, o czym
system operacyjny Windows poinformowałby nas komunikatem podobnym
do: „Program .... nie odpowiada. Trwa wyszukiwanie rozwiązania
przez system Windows.”. W konsekwencji pewnie otrzymalibyśmy
zapytanie, czy zamknąć program, czy poczekać, aż program zacznie
odpowiadać. Chyba nikt z nas nie lubi takich pytań (na które nie
ma prostej odpowiedzi). Chyba nikt z nas, programistów, nie
chciałby, by ich aplikacje działały w ten sposób.
Zastanówmy się jednak, dlaczego taka sytuacja mogła mieć miejsce.
Otóż nasza aplikacja odpytywała źródło danych w sposób
synchroniczny lub prościej, na każde zapytanie oczekiwana
była od razu odpowiedź. Aplikacja została zablokowana, gdyż po
wysłaniu żądania o dane, oczekiwała na odpowiedź, która nie
nadeszła lub nadejść miała po akceptowalnym czasie.
Asynchroniczność
W poprzednim przykładzie jednym ze źródeł problemów było
synchroniczne podejście do pobierania danych. Oczywiście innym
sposobem na pobieranie danych jest wykorzystanie podejścia
asynchronicznego. Otóż okazuje się, że wiele problemów,
można rozwiązać stosując właśnie podejście asynchroniczne.
Dzisiejszy świat zdaje się być stworzony do komunikacji
asynchronicznej. Przecież nie chcemy być blokowani w oczekiwaniu na
kolejną daną. Zauważmy ponadto, że źródeł danych może być
wiele, może zajść sytuacja, w której musimy połączyć dane z
wielu z nich.
Dlatego trudno się nie zgodzić, że:
- Asynchroniczność jest potrzebna niemal wszędzie.
- Asynchroniczne programowanie jest trudne.
- Komponowanie asynchronicznego kodu jest jeszcze trudniejsze.
Wyobraźmy sobie sytuacje, w której asynchroniczne obsługujemy
sieciowe źródło danych i jeśli się to powiedzie, to robimy coś
tam, a jeśli się nie uda to coś innego. No i jeszcze, gdy
dorzucimy do tego, że np. wszystko musi się wykonać w czasie
mniejszym niż 10 sekund, gdyż w przeciwnym razie nie będziemy
zainteresowani wynikiem. Musimy więc składać/komponować
zdarzenia, jednak jest to bardzo trudne. Ponadto możemy nie być
zainteresowaniu wszystkimi danymi, będziemy chcieli je wybierać,
czy filtrować. I oczywiście jesteśmy przyzwyczajeni do prostych
rozwiązań, a przecież najłatwiej przeglądać po prostu kolekcje
danych.
Misja Reactive Extensions
Wróćmy jednak do głównego tematu, czyli „Reactive Extensions”.
Otóż na głównej stronie tego projektu
(http://msdn.microsoft.com/en-us/data/gg577609)
można znaleźć następującą definicję:
„The Reactive Extensions (Rx)...
...is a library to compose asynchronous and event-based programs using observable collections and LINQ-style query operators.”Definicja ta krótko i zwięźle podsumowuje, czym jest Rx, ale przyznam, że musiałem przeczytać ją kilkakrotnie, zanim zrozumiałem detale. W każdym razie Reactive Extensions pozwalają na:
- Uproszczenie kodu związanego z programowaniem
asynchronicznym oraz opartym na zdarzeniach,
- Dają możliwość filtrowania lub komponowania (łączenia)
różnych asynchronicznych operacji oraz ich wyników (np. z
wykorzystaniem LINQ).
- Oferują inne podejście do obsługi kolekcji oraz zdarzeń.
W Rx są one traktowane jako źródła danych, które możemy
obserwować.
Skąd jednak wziąć owe biblioteki dla Reactive Extensions? Niestety
Rx nie jest częścią .NET 3.5 SP1 ani .NET 4.0. Można jednak dla
tych frameworków pobrać odpowiednie biblioteki, co więcej w .NET
4.0 wprowadzono już pewne elementy związane z podstawami Rx.
Również w przypadku Silverlight można skorzystać z Rx, aktualnie
wspierana jest wersja Silverlight 4 i eksperymentalnie Silverlight w
wersji 5, natomiast wersja Silverlight 3 była wspierane przez
starsze wersje Rx. Co ciekawe Rx jest dostępne standardowo w ramach
systemu Windows Phone 7 i jest zainstalowane w pamięci ROM
urządzenia (nie trzeba nic dodatkowo pobierać, czy instalować).
Dostępna jest również specjalna wersja Rx dla Java Script (RxJS).
Dla kompletności można również wspomnieć o platformie XNA 3 i 4,
które były wspierane przez starsze wersji Rx, ale wsparcie to nie
będzie już kontynuowane. W tym artykule skupimy się jednak na
wersji Rx dla .NET.
Reasumując Rx można zainstalować przy pomocy programu
instalacyjnego dostępnego pod adresem:
http://www.microsoft.com/download/en/details.aspx?id=26649
(trafić tu można przez MSDN > Learn > Reactive Extensions
(http://msdn.microsoft.com/en-us/data/gg577609
) > Get it) lub prościej przy użyciu NuGet'a (wyszukujemy Rx).
c.d.n. ...
Ten wpis jest bardzo interesujący
OdpowiedzUsuńTen wpis jest bardzo ciekawy
OdpowiedzUsuń