Introduction to Reactive Extensions (Rx)

Preview:

DESCRIPTION

Presentations from the june meeting of IDNDUG http://ariely.info/Communities/IDNDUG/IDNDUG19thJune2013/tabid/171 The Reactive Extensions (Rx) is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators. Using Rx, developers represent asynchronous data streams with Observables, query asynchronous data streams using LINQ operators, andparameterize the concurrency in the asynchronous data streams using Schedulers. Simply put, Rx = Observables + LINQ + Schedulers

Citation preview

Tamir DresherSenior Software ArchitectJune 19, 2013

Slides: Bart De Smet

Reactive Extensions (RX)

About Me

• Software architect, consultant and instructor• Technology addict• 10 years of experience• .NET and Native Windows Programming• http://www.TamirDresher.com.

Socialmedia

Stock tickers

RSS feeds

GPS

Server managementUI e

vents

Applications And Data

Reactive Extensions Architecture

Concurrency

IScheduler TimeThreads Cloud Dispatchers

Event Streams

IObservable<T>

IObserver<T>ISubject<T>

LINQ to Events

from quote in stockwhere quote.Symbol == “MSFT”select quote.ValueProjectionFi

lterin

gAggregating

Gro

upin

g Joins

WindowingSharing

SamplingThrottling Timeout

Merging

Recovery

The building blocks

• Observables– Producers (.NET events, WinRT Events, Sensors, APM method etc.)

• Observers– Consumers

Observable

Subscribe

Observer

Essential Interfacesnamespace System{

public interface IObservable<out T>{

IDisposable Subscribe(IObserver<T> observer);}

public interface IObserver<in T>{

void OnNext(T value); void OnError(Exception error);

void OnCompleted;)(} }

Notification Grammar

OnNext(42)

source1

OnNext(43) OnCompleted

OnNext(“Hello”)

source2

OnError(error)

OnNext* (OnError | OnCompleted)?

Limitations of .NET Events

exchange.StockTick += (sender, args) =>{ if (args.Quote.Symbol == “MSFT”) { // Imperative code }};

exchange.StockTick -= /* what goes here? */;

Can’t pass around Hidden data source

Hard resource maintenance

Lack of composition

Observable Sequences to the Rescue

IObservable<Quote> stockQuotes = …;

var msft = stockQuotes

.Where(quote => quote.Symbol == “MSFT”);

var subscription = msft.Subscribe(quote => /* … */);

subscription.Dispose();

Easy resource maintenance

Can define query operators

ReactDictionary web

service

Asynchronous request

ReactionReactiveReactor

IObservable<string>

IObservable<DictionaryWord[]>Data binding

on UI thread

“React”

Dictionary Suggest

Demo

Converting Events and Asynchronous Methods

// Convert the TextChanged event to IObservable<string>var input = (from evt in Observable.FromEventPattern(txt, “TextChanged”) select ((TextBox)evt.Sender).Text) .Throttle(TimeSpan.FromSeconds(0.5)) .DistinctUntilChanged();

// Convert asynchronous proxy methods to Func<string, IObservable<string[]>>var lookup = Observable.FromAsyncPattern<string, string[]>(svc.BeginLookup, svc.EndLookup);

// Compose both sources using a queryvar res = from term in input from words in lookup(term).TakeUntil(input) select words;

No longer needed in Rx v2.0 for .NET 4.5, using Task<T>

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

from tick in ticks

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

27.01 27.96 31.21 30.73

MSFT

21.75 22.54 20.98

INTC

from tick in ticks

group tick by tick.Symbol into company

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

MSFT

INTC

from tick in ticks

group tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)

[27.01, 27.96] [27.96, 31.21] [31.21, 30.73]

[21.75, 22.54] [22.54, 20.98]

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

MSFT

INTC

from tick in ticksgroup tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)

let diff = (openClose[1] – openClose[0]) / openClose[0]

0.034 0.104 -0.015

0.036 -0.069

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

MSFT

INTC

from tick in ticksgroup tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)let diff = (openClose[1] – openClose[0]) / openClose[0]

where diff > 0.1

0.034 0.104 -0.015

0.036 -0.069

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

from tick in ticksgroup tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)let diff = (openClose[1] – openClose[0]) / openClose[0]where diff > 0.1

select new { Company = company.Key, Increase = diff }

res

Company = MSFTIncrease = 0.104

Reactive Extensions Architecture

Event Streams

IObservable<T>

IObserver<T>ISubject<T>

LINQ to Events

from quote in stockwhere quote.Symbol == “MSFT”select quote.ValueProjectionFi

lterin

g

AggregatingG

roup

ing

Joins

Windowing

Sharing

Sampling

Throttling Timeout

Merging

Recovery

The Role of SchedulersParameterize Concurrency

//// Runs a timer on the default scheduler//IObservable<long> Timer(TimeSpan dueTime);

//// Every operator that introduces concurrency// has an overload with an IScheduler//IObservable<long> Timer(TimeSpan dueTime, IScheduler scheduler);

The Role of SchedulersSynchronization

var xs = Observable.Return(42, Scheduler.ThreadPool);xs.Subscribe(x => lbl.Text = "Answer = " + x);

xs.ObserveOn(new ControlScheduler(frm)) .Subscribe(x => lbl.Text = "Answer = " + x);xs.ObserveOn( frm ) .Subscribe(x => lbl.Text = "Answer = " + x);

The IScheduler Interface

public interface IScheduler{ DateTimeOffset Now { get; }

IDisposable Schedule<TState>( TState state, Func<IScheduler, TState, IDisposable> action);

IDisposable Schedule<TState>( TimeSpan dueTime, TState state, Func<IScheduler, TState, IDisposable> action);

IDisposable Schedule<TState>( DateTimeOffset dueTime, TState state, Func<IScheduler, TState, IDisposable> action);}

Operational Layering of Rx

public static IObservable<T> Return<T>(T value, IScheduler scheduler){ return Observable.Create<T>(observer => { // Serialize state to scheduler; return ability to cancel return scheduler.Schedule(new { value, observer }, (_, x) => { x.observer.OnNext(x.value); x.observer.OnCompleted(); return Disposable.Empty; // No recursive work }); });}

Virtualizing Time for Testing

var scheduler = new TestScheduler();

var input = scheduler.CreateHotObservable( OnNext(300, “Bart De Smet”), OnNext(400, “Erik Meijer”), OnCompleted<string>(500));

var results = scheduler.Start(() => from name in input select name.Length);

results.Messages.AssertEqual( OnNext(300, 12), OnNext(400, 11), OnCompleted<int>(500));

The Asynchronous Programming Landscape

Synchronous Asynchronous

Sing

le v

alue

(1)

Mul

tiple

val

ues

(*)

Func<T> Task<T>

IEnumerable<T> IObservable<T>

var y = f(x);var z = g(y);

var y = await fAsync(x);var z = await gAsync(y);

var res = from p in products where p.Name == “Rx” select p.Price;

foreach (var x in res) …

var res = from s in stocks where s.Symbol == “MSFT” select q.Quote

res.Subscribe(x => …

Summary

• Tame your event streams using Rx and LINQ!

• Download Rx today!– Through http://www.microsoft.com/download (search for Rx SDK)– Using NuGet @ www.nuget.org (search for Rx-Main)

• Watch videos at http://channel9.msdn.com/tags/Rx

Related Content/* Only get the value from each key up */var keyups = Rx.Observable.fromEvent(input, 'keyup') .select(function (e) { return e.target.value; }) .where(function (text) { return text.length > 2; });

/* Now throttle/debounce the input for 500ms */var throttled = keyups .throttle(500 /* ms */);

/* Now get only distinct values, so we eliminate the arrows */var distinct = keyups .distinctUntilChanged();

void PrintPrimes(int n) { std::cout<<"Rx: first "<<n<<" primes squared"<<endl; auto values = rxcpp::Range(2); rxcpp::from(values) .where(IsPrime) .select([](int x) { return std::make_pair(x, x*x); }) .take(n) .for_each(rxcpp::MakeTupleDispatch(

[](int p, int s) { cout<<p<<" =square=> "<<s<<endl; }));

}

RX++RxJS

28

ReactiveUIpublic class NewUserViewModel : ReactiveObject{

// This is ReactiveUI's version of implementing INotifyPropertyChangedstring _Password,_PasswordConfirmation;public string Password {

get { return _Password; }set { this.RaiseAndSetIfChanged(x => x.Password, value); }

}public string PasswordConfirmation {

get { return _PasswordConfirmation; }set { this.RaiseAndSetIfChanged(x => x.PasswordConfirmation, value); }

}ICommand OkCommand { get; protected set; }public NewUserViewModel(){

var canHitOk = this.WhenAny(x => x.Password, x => x.PasswordConfirmation,(pass, confirm) => (pass.Value == confirm.Value && pass.Value.Length > 3));OkCommand = new ReactiveCommand(canHitOk);

}

Resources

• Channel 9– Curing Your Event Processing Blues with Reactive Extensions (Rx) -

Bart De Smet http://msdn.microsoft.com/en-us/library/windowsazure/jj860549.aspx

• IntroToRx.com– IntroToRx.com is the online resource for getting started with

the Reactive Extensions to .Net.• www.reactiveui.com

https://github.com/reactiveui/ReactiveUI.Samples

Presenter contact detailsc: +972-52-4772946e: tamirdr@codevalue.netb: TamirDresher.comw: www.codevalue.net

Recommended