390 likes | 572 Views
Wprowadzenie do Reactive eXtensions dla .NET (RX). Autor: Maciej Zbrzezny Rule Financial, Łódzka Grupa Profesjonalistów IT & . NET 2011.11.03. O mnie. Nazywam się Maciej Zbrzezny P racuje w firmie Rule Financial. Tworzę oprogramowanie wykorzystujące platformę .NET(głównie C #).
E N D
Wprowadzenie do ReactiveeXtensions dla .NET (RX) Autor: Maciej Zbrzezny Rule Financial, Łódzka Grupa Profesjonalistów IT & .NET 2011.11.03
O mnie • Nazywam się Maciej Zbrzezny • Pracuje w firmie Rule Financial. • Tworzę oprogramowanie wykorzystujące platformę .NET(głównie C#). • Autor bloga „Programowanie i Technologie” (http://maciej-progtech.blogspot.com/). • MCPD Windows Developer 4.0 • MCTS ASP.NET 3.5. • maciejzbrzezny@gmail.com • @MaciejZbrzezny
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 Daj mi Dane Przetwarzam Dane
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 composeasynchronous and event-based programs using observable collections and LINQ-stylequery 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 experimentalrelease, 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 • Instalkahttp://www.microsoft.com/download/en/details.aspx?id=26649 (trafić do niej można przez MSDN > Learn > Reactive Extensions (http://msdn.microsoft.com/en-us/data/gg577609) > Get it) • NuGet (szukamy RX)
Przypominamy sobie Enumerator public interfaceIEnumerable<T> { IEnumerator<T> GetEnumerator(); } public interfaceIEnumerator<T>: IDisposable { T Current { get; } boolMoveNext(); void Reset(); } Synchroniczny PULL
Przekształcamy … public interfaceIEnumerable<T> { IEnumerator<T> GetEnumerator(void); } public interfaceIEnumerator<T>: IDisposable { T GetCurrent (void); boolMoveNext(void); void Reset(); }
Przekształcamy … public interfaceIEnumerable<T> { (IDisposable & IEnumerator<T> GetEnumerator(void); } public interfaceIEnumerator<T>: IDisposable { T GetCurrent (void); boolMoveNext(void)throwsException; }
Przekształcamy … public interfaceIEnumerableDual<T> { (IDisposable& IEnumerator<T> GetSetEnumerator(IEnumerator<T>); } public interfaceIEnumerator<T> { T GetCurrent (void); (true | false | Exception) MoveNext(void) throwsException; }
Przekształcamy … public interfaceIEnumerableDual<T> { IDisposableSetEnumerator( IEnumerator<T>); } public interfaceIEnumerator<T> { T GetCurrent (void); (true | false | Exception) MoveNext(void); }
Przekształcamy … public interfaceIEnumerableDual<T> { IDisposableSetEnumerator( IEnumerator<T>); } public interfaceIEnumerator<T> { T GetCurrent (void); (T| false | Exception) MoveNext(void); }
Przekształcamy … public interfaceIEnumerableDual<T> { IDisposableSetEnumerator( IEnumerator<T>); } public interfaceIEnumeratorDual<T> { voidMoveGotNext(T| false | Exception); }
Przekształcamy … public interfaceIEnumerableDual<T> { IDisposableSetEnumerator( IEnumerator<T>); } public interfaceIEnumeratorDual<T> { voidGotT(T); voidGotException (Exception); voidGotNothing (); }
Poznajmy IObservable i IObserver public interfaceIObservable<T> { IDisposableSubscribe( IObserver<T>); } public interfaceIObserver<T> { voidOnNext(T); voidOnException (Exception); voidOnCompleted (); } Asynchroniczny PUSH
Obserwowanie i subskrypcja zamiast przeglądania Jestem zainteresowany Danymi (subscribe) Przetwarzam Dane Error Dane KONIEC
Obserwowanie i subskrypcja zamiast przeglądania • Konstruujemy / pobieramy IObservable. (W Rxjest wiele metod pomocniczych tworzące IObservable z tablic, list, zdarzeń, ….) • Subskrybujemy przekazując nasz obserwator (IObserver) lub odpowiednie delegacje. • Wykonujemy „Dispose” na subskrypcji której dłużej nie potrzebujemy client IObservable<T> Subscription 1 OnNext() OnNext() OnNext() OnNext() Subscription 2 OnNext() OnNext()
Reactive.Concurrency i Scheduler • CurrentThreadScheduleriScheduler.CurrentThread • ImmediateScheduleriScheduler.Immediate • NewThreadScheduleriScheduler.NewThread • TaskPoolScheduleriScheduler.TaskPool • ThreadPoolScheduleriScheduler.ThreadPool • Dodatkowo: • System.Reactive.Windows.Threading.dll: DispatcherScheduler • System.Reactive.Windows.Forms.dll: ControlScheduler
Observables (1) OnCompleted • Observable.Empty<int>() • Observable.Return(777) • Observable.Throw<int>(newException("msg")) • Observable.Never<int>() • Observable.Range(0,2) newint[0] OnNext newint[]{777} Iterator rzuca Exception OnError Iterator zawiesił się OnNext OnNext Enumerable.Range (0,2)
Observables (2) • Observable.Interval ( TimeSpan.FromMilliseconds (100)); • Observable.Generate( 0, i => i < 10, i => i + 1, i => i); • Observable.Create<int>( observer => { observer.OnNext( 77 ); observer.OnCompleted(); return ( () => { } ); } ); • I inne … Nowa wartość co 100 ms for(int i=0;i<10;i++) yield return i; // dostępne również // z opóźnieniem // czasowym • Przekazujemy delegatę o patametrzeIObservable • Działamy na IObservable • Zwracamy delegatę dla Dispose
Ciepło– zimno, czyli zimne i ciepłe źródła Zimne – zawsze te same dane po subskrypcji client IObservable<T> 0, 1, 2, 3, … Subscription 1 Subscription 2 0, 1, 2, 3, … Subscribe() client IObservable<T> Mouse Events Ciepłe – zawsze aktualne dane [x1,y1] [x2,y2] … Subscription 1 Subscription 2 [x2,y2] [x3,y3] … Subscribe()
Zdarzenia w .NET niby pożyteczne, łatwe, ale… myForm.MouseMove += (sender, args) => { if (args.Location.X == args.Location.Y) // chcę wywołać inne zdarzenie }. myForm.MouseMove -= /* a co tutaj?? */ Jak przekazywać? Ukryte źródło danych Jak filtrować? Jak obsługiwać błędy ?? Jak komponować zdarzenia? Co z uwalnianiem zasobów?
… obserwowanie jest lepsze Źródło punktów IObservable<Point> mouseMoves = Observable.FromEventPattern<MouseEventArgs> (this, "MouseMove" ) .Select( ev => ev.EventArgs.Location ); varfiltered = mouseMoves .Where(pos => pos.X == pos.Y); varsubscription = filtered.Subscribe ( …) Subscription.Dispose(); Obiekty można przekazywać Łatwo można filtrować Są inne operatory pozwalające na kompozycję Łatwo zwalniamy zasoby
Operatory LINQ na IObservable IObservable<T> IObservable<T>
Komponowanie strumieni… --A--A--A--| ----B--B--B--| Amb --A--A--A--| • Amb • Concat • SelectMany • Merge • Zip • CombineLatest • ForkJoin --A--A--A--| -----------B--B--B--| Concat --A--A--A--B--B--B--| -(AX)(AY)(BX)(BY)(AZ)(CX)(BZ)(CY)(CZ)| --A--B--C--| --X--Y--Z--| SelectMany -A--B--C---| --X--Y--Z--| Merge --AX-BY-CZ--| -A--B--C---| --X--Y--Z--| Zip -(AX)-(BY)-(CZ)--| -A----B--C--| -UWXYZ--| CombineLatest -(AU)(AW)(BX)(BY)(CZ)| -A----B--C--| -UWXYZ--| ForkJoin -----------(CZ)--|
Tematy (Subject) • Subject może być obserwowany (jest IObservable) • Subject jest obserwatorem (jest IObserver) • Wariacje: • ReplaySubject: - oferuje pełną historię • AsyncSubject – oferuje to co zostało wrzucone na końcu i kończy się • BehaviorSubject: podobnie jakReplaySubjectale z pamięcią 1 elementu. IObservable<T> IObservable<T> OnNext OnNext OnNext OnNext Subject OnNext OnNext OnNext OnNext Client
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 Rx = Observables+ LINQ + Schedulers
Rule Financial - szuka • C# developer • Senior C# developer • Developer .NET/Silverlight • http://www.rulefinancial.com/careers/global-vacancies.aspx