30
Tamir Dresher Senior Software Architect June 19, 2013 Slides: Bart De Smet Reactive Extensions (RX)

Introduction to Reactive Extensions (Rx)

Embed Size (px)

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

Page 1: Introduction to Reactive Extensions (Rx)

Tamir DresherSenior Software ArchitectJune 19, 2013

Slides: Bart De Smet

Reactive Extensions (RX)

Page 2: Introduction to 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.

Page 3: Introduction to Reactive Extensions (Rx)

Socialmedia

Stock tickers

RSS feeds

GPS

Server managementUI e

vents

Applications And Data

Page 4: Introduction to Reactive Extensions (Rx)

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

Page 5: Introduction to Reactive Extensions (Rx)

The building blocks

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

• Observers– Consumers

Observable

Subscribe

Observer

Page 6: Introduction to Reactive Extensions (Rx)

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;)(} }

Page 7: Introduction to Reactive Extensions (Rx)

Notification Grammar

OnNext(42)

source1

OnNext(43) OnCompleted

OnNext(“Hello”)

source2

OnError(error)

OnNext* (OnError | OnCompleted)?

Page 8: Introduction to Reactive Extensions (Rx)

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

Page 9: Introduction to Reactive Extensions (Rx)

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

Page 10: Introduction to Reactive Extensions (Rx)

ReactDictionary web

service

Asynchronous request

ReactionReactiveReactor

IObservable<string>

IObservable<DictionaryWord[]>Data binding

on UI thread

“React”

Dictionary Suggest

Page 11: Introduction to Reactive Extensions (Rx)

Demo

Page 12: Introduction to Reactive Extensions (Rx)

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>

Page 13: Introduction to Reactive Extensions (Rx)

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

from tick in ticks

Page 14: Introduction to Reactive Extensions (Rx)

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

Page 15: Introduction to Reactive Extensions (Rx)

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]

Page 16: Introduction to Reactive Extensions (Rx)

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

Page 17: Introduction to Reactive Extensions (Rx)

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

Page 18: Introduction to Reactive Extensions (Rx)

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

Page 19: Introduction to Reactive Extensions (Rx)

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

Page 20: Introduction to Reactive Extensions (Rx)

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);

Page 21: Introduction to Reactive Extensions (Rx)

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);

Page 22: Introduction to Reactive Extensions (Rx)

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);}

Page 23: Introduction to Reactive Extensions (Rx)

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 }); });}

Page 24: Introduction to Reactive Extensions (Rx)

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));

Page 25: Introduction to Reactive Extensions (Rx)

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 => …

Page 26: Introduction to Reactive Extensions (Rx)

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

Page 27: Introduction to Reactive Extensions (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

Page 28: Introduction to Reactive Extensions (Rx)

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);

}

Page 29: Introduction to Reactive Extensions (Rx)

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

Page 30: Introduction to Reactive Extensions (Rx)

Presenter contact detailsc: +972-52-4772946e: [email protected]: TamirDresher.comw: www.codevalue.net