This document provides an overview of Reactive Extensions (Rx) for .NET, which is a new API that enables "LINQ over Events". It introduces key Rx concepts like Observables, Observers, pushing vs pulling data, and dualizing interfaces like IEnumerable/IEnumerator to provide a standard way to work with pushed data. It also demonstrates how to create Observables from different sources and use important Rx operators like Merge, Zip, GroupBy. Overall it serves as an introduction to understanding and working with the Rx framework for .NET.
1. Reactive Extensions for .Net Scott Weinstein Principal Lab49 weblogs.asp.net/sweinstein / @ScottWeinstein
2. What is it? The Reactive Extensions for .Net are a new API from MS Dev labs to enable “Linq over Events” Why should I care? Offers a better programming model then Events
6. Pull For pull, data is processed at the leisure of the consumer. The consumer “pulls” the next item from the producer Common examples include: reading from a file summing the numbers in an array iterating though a database query traversing a directory listing paging through an Amazon search
7. Push For push, data is send via demands of the source. The producer pushes the data to the consumer. Common examples include: Device measurements such as time light heat User triggered data such as Mouse & Keyboard events UI events Sales transactions Asynchronous code
8. Push & Pull In both scenarios, data moves from the producer to the consumer
9. Push & Pull in .Net In .Net Pulled data is exposed via common interface pair IEnumerable/IEnumerator There is no other way Foreach and Linq are build on these interfaces Pushed data is exposed via Events Ad-hoc delegate callbacks Ad-hoc subscribe/callback interfaces BeginXXX/EndXXX Async pattern 3rd party attempts at Linq for Pushed data (Clinq,Slinq,PushLinq) Each implementation is unique is its own special way
10. LINQ LINQprovides a composable and standard way to do list manipulations The Reactive Extensions (RX) attempt to Provide a common interface for Pushed data IObservable/IObserver Enable Linq over Pushed data, providing composiblity and standard operators
13. Func and Action and Lambdas Func<int> a; Func<int,int,int> add = (a,b) => a+b; Action<T> t; Action <T,T> tt;
14. Some (Category) Theory There is a formal basis for the RX Duality, as such, is the assertion that truth is invariant under this operation on statements. In other words, if a statement is true about C, then its dual statement is true about Cop. Also, if a statement is false about C, then its dual has to be false about Cop. Informally, these conditions state that the dual of a statement is formed by reversing arrows and compositions. What this means is that if we can create a Dual of IEnumerable then all of Linq will work over pushed data
15. Dualizing IEnumerator interface IEnumerator<T> { T Current { get; } // but can throw an exception bool MoveNext(); void Reset(); // not used } Reverse the arrows interface IObserverDraft1<T> { SetCurrent(T value); // but need to handle an exception MoveNext(bool can) ; }
16. Dualizing IEnumerator (2/2) interface IObserverDraft2<T> { OnNext(T value); OnError(Exception ex); MoveNext(bool can) ; //but called every time! } interface IObserver<T> { OnNext(T value); OnError(Exception ex); OnCompleted(); // only called once }
17. Dualizing IEnumerable interface IEnumerable<T> { IEnumerator<T> GetEnumerator(); } Reverse the arrows public interface IObservableDraft1<T> { // But how do I stop observing? SetObserver(IObserver<T> obs); }
18. Dualizing IEnumerable (2/2) interface IObservableDraft2<T> { Subscribe(IObserver<T> obs); // can I be more composable? Unsubscribe(IObserver<T> obs); } interface IObservable<T> { IDisposable Subscribe(IObserver<T> obs); }
21. Some useful Combinators CombineLatest Do ForkJoin GroupBy Scan HoldUntilChanged Interval Merge ObserveOnDispatcher Sample Throttle Select SelectMany Where Zip
22. How to create Observables? Create CreateWithDisposable FromAsyncPattern FromEvent Generate ISubject In general, it’s a mistake to create custom implementations of IObservable or IObserver When might it be ok to break this rule?
27. Hot & Cold Observables (and Enumerables) come in two flavors Hot Values exist outside of subscription Cold Value only exist because of subscription Cold observables can be prone to side-effects ToArray() is one method for making cold Enumerables hot, Replay() and Publish for Observables (and now Enumerables)
29. Code vs. Data RX has an alternate method of representing stream events Interface defines a code-centric view OnNext OnError OnCompleted Notification defines a data-centric view new Notification<T>.OnNext(T next) Where is this useful?
30. Schedulers RX introduces Schedulers for explicit control Which thread do subscriptions run on How is time represented ControlSchedulerCurrentThreadScheduler DispatcherSchedulerImmediateScheduler NewThreadSchedulerSynchronizationContextScheduler TaskPoolSchedulerThreadPoolScheduler
31. Topics not covered Joins Subjects combine Observability and Enumerablility into a single class. BehaviorSubject<T> AsyncSubject<T> ReplaySubject<T> Subject<T>
32. How to get it? Download from the DevLabs: Reactive Extensions for .NET (Rx) site .Net 4 In .Net 4 – IObservable/IObserver are part of the BCL .Net 3.5 SP1 Silverlight 3 Javascript Current license is “go-live” however the API is still evolving