You are on page 1of 36

Wprowadzenie do Reactive

eXtensions dla .NET (RX)

Łódzka Grupa Profesjonalistów IT & .NET


Dla kogo?
 Czy zdarzyło Ci się tworzyć aplikacje, które
wykorzystywały wywołania asynchroniczne?
 Czy, wywołania asynchroniczne sprawiły problemy?
 Czy wolałbyś otrzymywać dane zamiast o każdą daną się
dopraszać?
 Czy znasz LINQ i chciałbyś go wykorzystywać w
większym zakresie?
Problem: pobieranie danych
Asynchroniczność
 Dzisiejszy świat jest asynchroniczny, a my nie chcemy być
blokowani
 Źródeł danych może być wiele, co w przypadku, gdy
musimy połączyć dane z wielu z nich
 Możemy nie być zainteresowaniu wszystkimi danymi jak je
wybierać, czy filtrować
 Jesteśmy przyzwyczajeni do prostych rozwiązań, najłatwiej
przeglądać po prostu kolekcje danych
Misja RX
The Reactive Extensions (Rx)...

...is a library to compose asynchronous and event-based


programs using observable collections and LINQ-style
query operators.
Rx …
 Pozwala na uproszczenie kodu związanego z
programowaniem asynchronicznym oraz opartym na
zdarzeniach,
 Daje możliwość komponowania (łączenia) różnych
asynchronicznych operacji oraz ich wyników.
 Oferuje inne podejście do kolekcji oraz zdarzeń. W Rx są
one traktowane jako źródła danych, które możemy
obserwować.
Skąd wziąć RX?
 Nie ma RX w .NET 3.5 SP1 ani .NET 4.0, ale:
 Można dla nich pobrać
 W .NET 4.0 przygotowano już pewne ułatwienia
 Rx jest też dostępne dla:
 Silverlight 4 (5 w experimental release, 3 –starsze wersje RX)
 Windows Phone 7 (dostępne już w ROM)
 XNA 3 i 4 (starsze wersje RX, nie będzie wsparcia)
 Reactive Extensions for JavaScript (RxJS)
Jak pobrać RX
 Instalka
http://www.microsoft.com/download/en/details.aspx?id=2
6649 (trafić do niej można przez MSDN > Learn >
Reactive Extensions (http://msdn.microsoft.com/en-
us/data/gg577609) > Get it)
 NuGet (szukamy RX)
Kolekcje
Przypominamy sobie Enumerator

public interface IEnumerable<T>


{
IEnumerator<T> GetEnumerator();
}

public interface IEnumerator<T>: IDisposable


{
T Current { get; }
bool MoveNext();
void Reset();
}
Przekształcamy …

public interface IEnumerable<T>


{
IEnumerator<T> GetEnumerator(void);
}

public interface IEnumerator<T>: IDisposable


{
T GetCurrent (void);
bool MoveNext(void);
void Reset();
}
Przekształcamy …

public interface IEnumerable<T>


{
(IDisposable & IEnumerator<T> GetEnumerator(void);
}

public interface IEnumerator<T>: IDisposable


{
T GetCurrent (void);
bool MoveNext(void) throws Exception;
}
Przekształcamy …

public interface IEnumerableDual<T>


{
(IDisposable & IEnumerator<T> GetSetEnumerator(
IEnumerator<T>);
}

public interface IEnumerator<T>


{
T GetCurrent (void);
(true | false | Exception) MoveNext(void) throws Exception;
}
Przekształcamy …

public interface IEnumerableDual<T>


{
IDisposable SetEnumerator( IEnumerator<T>);
}

public interface IEnumerator<T>


{
T GetCurrent (void);
(true | false | Exception) MoveNext(void);
}
Przekształcamy …

public interface IEnumerableDual<T>


{
IDisposable SetEnumerator( IEnumerator<T>);
}

public interface IEnumerator<T>


{
T GetCurrent (void);
(T| false | Exception) MoveNext(void);
}
Przekształcamy …

public interface IEnumerableDual<T>


{
IDisposable SetEnumerator( IEnumerator<T>);
}

public interface IEnumeratorDual<T>


{
void MoveGotNext(T| false | Exception);
}
Przekształcamy …

public interface IEnumerableDual<T>


{
IDisposable SetEnumerator( IEnumerator<T>);
}

public interface IEnumeratorDual<T>


{
void GotT(T);
void GotException (Exception);
void GotNothing ();
}
Poznajmy IObservable i IObserver

public interface IObservable<T>


{
IDisposable Subscribe( IObserver<T>);
}

public interface IObserver<T>


{
void OnNext(T);
void OnException (Exception);
void OnCompleted ();
}
Obserwowanie i subskrypcja zamiast
przeglądania
Obserwowanie i subskrypcja zamiast
przeglądania
 Konstruujemy / pobieramy
OnNext()
IObservable. (W Rx jest Subscription 1 OnNext()

IObservable<T>
OnNext()
wiele metod pomocniczych
tworzące IObservable z
tablic, list, zdarzeń, ….) OnNext()
Subscription 2 OnNext()
OnNext()
 Subskrybujemy przekazując
nasz obserwator client
(IObserver) lub
odpowiednie delegacje.
 Wykonujemy „Dispose” na
subskrypcji której dłużej nie
potrzebujemy
Do dzieła….
Reactive.Concurrency i Scheduler
 CurrentThreadScheduler i Scheduler.CurrentThread
 ImmediateScheduler i Scheduler.Immediate
 NewThreadScheduler i Scheduler.NewThread
 TaskPoolScheduler i Scheduler.TaskPool
 ThreadPoolScheduler i Scheduler.ThreadPool
 Dodatkowo:
 System.Reactive.Windows.Threading.dll: DispatcherScheduler
 System.Reactive.Windows.Forms.dll: ControlScheduler
Observables (1)
OnCompleted
 Observable.Empty<int>() new int[0]

OnNext new int[]{777}


 Observable.Return(777)
Iterator rzuca
OnError
 Observable.Throw<int>(new Exception

Exception("msg"))
Iterator
zawiesił się
 Observable.Never<int>()
OnNext OnNext Enumerable
 Observable.Range(0,2) .Range (0,2)
Observables (2)
 Observable.Interval ( Nowa wartość co
TimeSpan.FromMilliseconds (100)); 100 ms
 Observable.Generate(
for(int i=0;i<10;i++)
0,
yield return i;
i => i < 10, // dostępne również
i => i + 1, // z opóźnieniem
i => i); // czasowym
 Observable.Create<int>( • Przekazujemy
observer => delegatę o
{ patametrze
observer.OnNext( 77 ); IObservable
observer.OnCompleted(); • Działamy na
return ( () => { } ); IObservable
} ); • Zwracamy
delegatę dla
 I inne … Dispose
Do dzieła….
Ciepło – zimno, czyli zimne i ciepłe źródła

Zimne –

IObservable<T>
Subscription 1 0, 1, 2, 3, …

zawsze te same Subscription 2 0, 1, 2, 3, …


dane po Subscribe()
client
subskrypcji

Ciepłe –

IObservable<T>
Subscription 1 [x1,y1] [x2,y2] …

Mouse Events
zawsze Subscription 2 [x2,y2] [x3,y3] …
aktualne dane client
Subscribe()
Zdarzenia w .NET niby pożyteczne, łatwe,
ale…

Jak przekazywać? Ukryte źródło danych

myForm.MouseMove += (sender, args) =>


{ Jak filtrować?
if (args.Location.X == args.Location.Y)
// chcę wywołać inne zdarzenie Jak obsługiwać
błędy ??
}. Jak komponować zdarzenia?

myForm.MouseMove -= /* a co tutaj?? */
Co z uwalnianiem zasobów?
… obserwowanie jest lepsze Źródło
punktów
IObservable<Point> mouseMoves =
Observable.FromEventPattern<MouseEventArgs>
Obiekty (this, "MouseMove" )
można
przekazywać .Select( ev => ev.EventArgs.Location );
Łatwo można
filtrować
var filtered = mouseMoves
.Where(pos => pos.X == pos.Y); Są inne
operatory
pozwalające na
var subscription = filtered.Subscribe ( …) kompozycję

Subscription.Dispose();
Łatwo
zwalniamy
zasoby
Operatory LINQ na IObservable
IObservable<T>

IObservable<T>
Where Skip Take Select
Komponowanie strumieni…
--A--A--A--|
 Amb Amb --A--A--A--|
----B--B--B--|

--A--A--A--|
 Concat -----------B--B--B--|
Concat --A--A--A--B--B--B--|

 SelectMany --A--B--C--|
SelectMany
-(AX)(AY)(BX)(BY)
--X--Y--Z--| (AZ)(CX)(BZ)(CY)(CZ)|

 Merge -A--B--C---|
Merge --AX-BY-CZ--|
--X--Y--Z--|

 Zip -A--B--C---|
Zip -(AX)-(BY)-(CZ)--|
--X--Y--Z--|

 CombineLatest -A----B--C--|
CombineLatest -(AU)(AW)(BX)(BY)(CZ)|
-UWXYZ--|

 ForkJoin -A----B--C--| -----------(CZ)--|


ForkJoin
-UWXYZ--|
Do dzieła….
Tematy (Subject)
 Subject może być obserwowany IObservable<T> IObservable<T>
(jest IObservable)
Subject jest obserwatorem (jest

OnNext

OnNext
OnNext

OnNext

IObserver)
 Wariacje:
 ReplaySubject: - oferuje pełną Subject
historię

OnNext

OnNext
OnNext

OnNext
 AsyncSubject – oferuje to co
zostało wrzucone na końcu i kończy
się
 BehaviorSubject: podobnie jak
ReplaySubject ale z pamięcią 1 Client
elementu.
Do dzieła….
Literatura
 Channel 9 a zwłaszcza:
 Mike Taulty - Reactive Extensions for .NET for the Rest of Us:
http://channel9.msdn.com/Events/DevDays/DevDays-2011-
Netherlands/Devdays014
 Bart de Smet - DevCamp 2010 Keynote - Rx: Curing your
asynchronous programming blues:
http://channel9.msdn.com/Blogs/codefest/DC2010T0100-
Keynote-Rx-curing-your-asynchronous-programming-blues
 Data Developer Center > Learn > Reactive Extensions
(Rx) > Beginner's Guide to Reactive Extensions for .NET
(http://msdn.microsoft.com/en-us/data/gg577611) a
zwłaszcza Design Guidelines.
Podsumowanie
Dziękuję za uwagę.
Pytania?

You might also like