Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Rx workshop

3,641 views

Published on

Workshop slides from the Alt.Net Seattle 2011 workshop. Presented by Wes Dyer and Ryan Riley. Get the slides and the workshop code at http://rxworkshop.codeplex.com/

Published in: Technology, Sports
  • microsoft rx presentation
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Rx workshop

  1. 1. Reactive ExtensionsWorkshop<br />Ryan Riley & Wes Dyer<br />
  2. 2. Logistics<br />30 minute sections<br />10 minutes presentation<br />10 minutes coding<br />10 minutes discussion<br />New partner every section<br />Prizes for best code during each section<br />
  3. 3. Where can I get them?<br />Install with NuGet<br />Download at MSDN Data Developer Center<br />
  4. 4. Outline<br />Introduction to Rx<br />A Unified Programming Model<br />The Power of Rx<br />RxJS<br />Schedulers<br />Event Processing<br />Reactive Coincidence<br />Continuations Everywhere<br />Programming the Cloud<br />
  5. 5. introduction to rx<br />like events but much better<br />
  6. 6. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  7. 7. Reactive Programming<br />In computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change.<br />http://en.wikipedia.org/wiki/Reactive_programming<br />
  8. 8. Why should I care?<br />GPS<br />RSS feeds<br />Stock tickers<br />Social<br />media<br />UI events<br />Server management<br />
  9. 9. Reactive Programming using Events<br />Declare<br />eventAction<int> E;<br />Publish<br />E(42);<br />Subscribe<br /> E += x => Console.WriteLine(x);<br />
  10. 10. Reactive Programming using Rx<br />Declare<br />ISubject<int> S = newSubject<int>();<br />Publish<br />S.OnNext(42);<br />Subscribe<br />S.Subscribe(x => Console.WriteLine(x));<br />
  11. 11. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  12. 12. classProgram {<br />ISubject<int> S = newSubject<int>();<br />static void Main() {<br />var p = newProgram();<br />p.S.Subscribe(x => Console.WriteLine(x));<br />p.S.OnNext(1);<br />p.S.OnNext(2);<br />p.S.OnNext(3);<br /> }<br />}<br />classProgram {<br />eventAction<int> E;<br />static void Main() {<br />var p = newProgram();<br />p.E += x => Console.WriteLine(x);<br />p.E(1);<br />p.E(2);<br />p.E(3);<br /> }<br />}<br />A Little Example<br />
  13. 13. Separate Publish from Subscribe <br />Both<br />Publish<br />Subscribe<br />
  14. 14. First-Class “Events”<br />An object is first-class when it:<br />can be stored in variables and data structures<br />can be passed as a parameter to a subroutine<br />can be returned as the result of a subroutine<br />can be constructed at runtime<br />has intrinsic identity (independent of any given name)<br />http://en.wikipedia.org/wiki/First-class_object<br />
  15. 15. First-Class “Events”<br />// stored<br />IObservable<string> textChanged = …;<br />// passed<br />voidProcessRequests(IObservable<string> input) {…}<br />// returned<br />IObservable<int> QueryServer() {…}<br />
  16. 16. Punctuation<br />classIObserver<in T><br />{<br />voidOnNext(T value);<br />voidOnError(Exception error);<br />voidOnCompleted();}<br />
  17. 17. Contract<br />Grammar: OnNext* [OnCompleted | OnError]<br />Serialized execution of observer’s methods<br />0<br />1<br />2<br />0<br />1<br />1<br />2<br />0<br />0<br />1<br />2<br />
  18. 18. Challenge: Simple Transformation<br />Implement Events.LengthChanged<br />ImplementObservables.LengthChanged<br />Output should be:<br />
  19. 19. Answer<br />Events<br />Observables<br />
  20. 20. Bridging from the Existing World<br />query asynchronous data streams<br />
  21. 21. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  22. 22. Empty<br />// complete immediately<br />Observable.Empty<int>();<br />
  23. 23. Return<br />// return 1 value<br />Observable.Return(1);<br />1<br />
  24. 24. Throw<br />// throw an exception<br />Observable.Throw(newException());<br />
  25. 25. Never<br />// never complete<br />Observable.Never<int>();<br />
  26. 26. Range<br />// return three values starting with 0<br />Observable.Range(0, 3);<br />1<br />2<br />0<br />
  27. 27. ToEnumerable / ToObservable<br />// enumerable to observable<br />Enumerable.Range(0, 3).ToObservable();<br />// observable to enumerable<br />Observable.Range(0, 3).ToEnumerable();<br />1<br />2<br />0<br />
  28. 28. Generate<br />// observable for loop<br />Observable.Generate(<br /> 0,<br /> i => i < 3,<br /> i => i + 1,<br /> i => i * i<br />);<br />1<br />4<br />0<br />
  29. 29. Create<br />// anything you please<br />Observable.Create<int>(observer =><br />{<br />IDisposableb = newBooleanDisposable();<br /> newThread(() =><br /> {<br />for (inti = 0; i < 3&& !b.IsDisposed; ++i)<br />observer.OnNext(i);<br />observer.OnCompleted();<br /> return () => {};<br /> }).Start();<br /> returnb;<br />});<br />1<br />4<br />0<br />
  30. 30. classProgram {<br /> static void Main() {<br /> Labellbl = newLabel();<br />Formfrm = newForm {<br /> Controls = { lbl}<br /> };<br />frm.MouseMove+= (s, args) => {};<br /> }<br />}<br />classProgram {<br /> static void Main() {<br />Labellbl = newLabel();<br />Formfrm = newForm {<br /> Controls = { lbl }<br />};<br />varmouseMoves= Observable<br />.FromEventPattern<MouseEventHandler,<br />MouseEventArgs>(<br /> x => frm.MouseMove += x,<br /> x => frm.MouseMove -= x);<br />mouseMoves.Subscribe(evt => {});<br /> }<br />}<br />Using Events<br />
  31. 31. classProgram {<br /> static void Main() {<br /> Labellbl = newLabel();<br />Formfrm = newForm {<br /> Controls = { lbl}<br /> };<br />frm.MouseMove+= (sender, args) =><br /> {<br /> if(args.Location.X==<br />args.Location.Y)<br /> {<br />lbl.Text =<br />args.Location.ToString();<br /> }<br /> };<br />Application.Run(frm);<br /> }<br />}<br />classProgram {<br /> static void Main() {<br />Labellbl = newLabel();<br />Formfrm = newForm {<br /> Controls = { lbl }<br />};<br />varmouseUps = …;<br />varmouseMoves= …;<br />varspecificMoves =<br /> fromup inmouseUps<br /> frommove inmouseMoves<br /> letlocation = move.EventArgs.Location<br /> wherelocation.X == location.Y<br /> selectnew { location.X, location.Y };<br /> using(specificMoves<br /> .Subscribe(evt => lbl.Text= evt.ToString()))<br /> {<br />Application.Run(frm);<br /> }<br /> }<br />}<br />LINQ to Events<br />
  32. 32. Challenge<br />Complete DictionarySuggest<br /><ul><li>Create an Observable from the TextChangedevent
  33. 33. Create an Observable from an asynchronous web request
  34. 34. Combine these two observables to react to text input changes to return web service results</li></li></ul><li>Answer<br />
  35. 35. The Power of Rx<br />taking control<br />
  36. 36. Monitoring<br />// anything you please<br />var input = Observable<br /> .FromEventPattern(txt, "TextChanged")<br /> .Select(evt => ((TextBox)evt.Sender).Text)<br /> .Timestamp()<br /> .Do((Timestamped<string> evt) => Console.WriteLine(evt))<br /> .Select(evt => evt.Value)<br /> .Where(evt => evt.Length > 4)<br /> .Do(evt => Console.WriteLine(evt));<br />
  37. 37. Too Many Events<br />
  38. 38. Duplication<br />
  39. 39. Race Condition<br />
  40. 40. Challenge<br />Find and apply the operators to fix these issues in DictionarySuggest<br />
  41. 41. Answer<br />
  42. 42. JavaScript<br />
  43. 43. Challenge<br />Port DictionarySuggest to RxJS<br />
  44. 44. Answer<br />
  45. 45. Schedulers<br />parameterizing concurrency<br />
  46. 46. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  47. 47. Parameterizing Concurrency<br />Observable.Timer(TimeSpan.FromSeconds(5))<br />Which timer?<br />System.Threading.Timer?<br />System.Timers.Timer?<br />System.Windows.Forms.Timer?<br />System.Windows.Threading.Timer?<br />Sleep on the current thread?<br />… ?<br />
  48. 48. Scheduler Abstraction<br />execution context<br />clock<br />execution policy<br />
  49. 49. Scheduler Interface<br />interfaceIScheduler<br />{<br />DateTimeOffset Now { get; }<br />IDisposable Schedule(Action work);<br />IDisposable Schedule(TimeSpandueTime, Action work);IDisposable Schedule(DateTimeOffsetdueTime, Action work);}<br />
  50. 50. Operational Layering<br />Operators<br />varxs = Observable.Range(1, 10, <br />Scheduler.ThreadPool);<br />var q = from x inxs<br />where x % 2 == 0<br />select -x;<br />q.Subscribe(Console.WriteLine);<br />
  51. 51. Operational Layering<br />Operators<br />Observables<br />varxs = newRangeObservable<int>(1, 10, <br />Scheduler.ThreadPool);<br />var q = newSelectObservable<int>(<br />newWhereObservable<int>(<br />xs,<br /> x => x % 2 == 0),<br /> x => -x);<br />q.Subscribe(<br /> newLambdaObserver<int>(Console.WriteLine));<br />
  52. 52. Operational Layering<br />Operators<br />Observables<br />var n = 0;<br />Scheduler.ThreadPool.Schedule(self => {<br />if (n < 10) {<br /> if ((n + 1) % 2 == 0)<br />Console.WriteLine(-(n + 1));<br /> n++;<br /> self();<br /> }<br />});<br />Schedulers<br />
  53. 53. Operational Layering<br />Operators<br />Observables<br />var n = 0;<br />Action<object> work = null;<br />work = _ =><br />{<br />if (n < 10) {<br /> if ((n + 1) % 2 == 0)<br />Console.WriteLine(-(n + 1));<br /> n++;<br />ThreadPool.QueueUserWorkItem(null, work);<br /> }};<br />ThreadPool.QueueUserWorkItem(null, work);<br />Schedulers<br />Native Concurrency<br />
  54. 54. One Interface to Rule Them All<br />
  55. 55. The Problem of Time<br />Operations can take a long time<br />Observable.Timer(TimeSpan.FromYears(1000))<br />
  56. 56. Some operators have time-based semantics<br />Observable.Timer(TimeSpan.FromSeconds(1))<br /> .Buffer(TimeSpan.FromSeconds(1))<br />The Problem of Time<br />6<br />0<br />4<br />5<br />1<br />2<br />3<br />0<br />1<br />4<br />2<br />3<br />5<br />6<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />1s<br />
  57. 57. When testing reactive programs, time is the problem.<br />…virtual time is the solution.<br />The Problem of Time<br />
  58. 58. Schedulers Revisited<br />
  59. 59. TestScheduler scheduler = newTestScheduler();<br />IObservable<string> input = scheduler.CreateObservable(<br />OnNext(300, “wes”),<br />OnNext(400, “ryan”),<br />OnCompleted(500));<br />var results = scheduler.Run(() =><br />input.Select(x => x.Length));<br />results.AssertEqual(<br />OnNext(300, 3),<br />OnNext(400, 4),<br />OnCompleted(500));<br />Unit Testing with Schedulers<br />
  60. 60. Implement MainForm.GetQuotes<br />ImplementMainForm.GetQuery<br />Challenge: Historical Data<br />
  61. 61. Answer<br />
  62. 62. event processing<br />the power of LINQ<br />
  63. 63. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  64. 64. Given: Stream of stock ticks<br />Find: 10% daily price increase<br />Event Processing<br />
  65. 65. Windowing<br />MSFT<br />30.73<br />MSFT<br />27.01<br />MSFT<br />27.96<br />INTC<br />21.75<br />MSFT<br />31.21<br />INTC<br />22.54<br />INTC<br />20.98<br />Group by symbol: GroupBy(t => t.Symbol)<br />
  66. 66. Aggregation<br />MSFT<br />INTC<br />30.73<br />27.01<br />27.96<br />31.21<br />21.75<br />22.54<br />20.98<br />Aggregate each day with previous day: Buffer(2, 1)<br />
  67. 67. Filtering<br />MSFT<br />INTC<br />31.21<br />30.73<br />27.01<br />27.96<br />27.96<br />31.21<br />21.75<br />22.54<br />22.54<br />20.98<br />Filter by price increase > 10%: Where(w => PriceIncrease(w) > .1)<br />
  68. 68. Reduce<br />MSFT<br />INTC<br />27.96<br />31.21<br />Reduce to a single stream: Merge()<br />
  69. 69. Done!<br />27.96<br />31.21<br />
  70. 70. from tick instockTicks<br />group tick bytick.SymbolintosymbolStream<br />from window insymbolStream.Buffer(2, 1)<br />let increase = PriceIncrease(window)<br />where increase > .1<br />select new { symbol = symbolStream.Key, increase }; <br />LINQ: Event Processing<br />source<br />group<br />aggregate<br />apply<br />filter<br />reduce<br />
  71. 71. Change MainForm.Query to compute the Average High and Average Low over the past 5 trading days as well as the current Close and Date<br />Challenge: Event Processing<br />
  72. 72. Answer<br />
  73. 73. Reactive coincidence<br />streaming windows<br />
  74. 74. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  75. 75. Event Duration<br />0<br />2<br />1<br />vs<br />0<br />2<br />1<br />
  76. 76. An Example<br />left <br />left<br />right<br />
  77. 77. Representing Duration<br />begin<br />begin<br />end<br />end<br />Window<br />
  78. 78. Store<br />
  79. 79. Reactive Coincidence<br />Which people are at the store while it is opened?<br />5/5<br />5/6<br />curley<br />moe<br />larry<br />
  80. 80. Reactive Coincidence<br />Which people are at the store while it is opened?<br />5/5<br />5/6<br />moe<br />larry<br />curley<br />moe<br />
  81. 81. LINQ Join<br />from opening instoreOpenings<br />join person inpersonArrives<br />onopening.Closeequalsperson.Leavesinto g<br />selectnew { opening.Day, People = g };<br />
  82. 82. Change query in MainForm.MainForm to compute a stream of deltas when the mouse is down<br />Challenge: Drag and Drop<br />
  83. 83. Answer<br />
  84. 84. Programming the cloud<br />a glimpse into the future<br />
  85. 85. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  86. 86. Distributed Queries<br />Cloud<br />results<br />query<br />
  87. 87. Observable.Timer(<br />TimeSpan.FromSeconds(1),<br />Scheduler.Azure)<br /> .ObserveLocally()<br /> .Subscribe(Console.WriteLine);<br />Distributed Queries<br />Send the query to the cloud<br />Send the results back<br />
  88. 88. Pass-by-Value<br /> [Serializable] classMyType { … }<br />Pass-by-Reference<br />classMyType : MarshalByRefObject{ … }<br />Distributed Parameters<br />
  89. 89. var x = 42;<br />scheduler.Schedule(() =><br />Console.WriteLine(x));<br />classClosure {<br />public intx;<br />public void M() {<br />Console.WriteLine(x);<br /> }<br />}<br />var closure = newClosure();<br />closure.x = 42;<br />scheduler.Schedule(closure.M);<br />Distributed Scheduling<br />Pass by value or reference?<br />
  90. 90. interfaceIScheduler {<br /> …<br />IDisposable Schedule<T>(T state, Action<T> work);<br /> …<br />}<br />Scheduler Interface Revisited<br />
  91. 91. var x = 42;<br />scheduler.Schedule(<br /> x,<br /> state =><br />Console.WriteLine(state));<br />static void M(int state) {<br />Console.WriteLine(state);<br />}<br />varx = 42;<br />scheduler.Schedule(<br /> x,<br /> M);<br />Distributed Scheduling<br />No closures!!!<br />
  92. 92. scheduler.Schedule(42, x =><br />scheduler.Schedule(x + 1, y =><br />Console.WriteLine(y)));<br />Nested Scheduling<br />
  93. 93. Distributed Scheduling<br />cloud<br />Scheduler<br />
  94. 94. interfaceIScheduler {<br /> …<br />IDisposable Schedule<T>(T state,<br /> Action<IScheduler, T> work);<br /> …<br />}<br />Scheduler Interface Rerevisited<br />
  95. 95. scheduler.Schedule(42, (s, x) =><br />s.Schedule(x + 1, y =><br />Console.WriteLine(y)));<br />Nested Scheduling<br />
  96. 96. Fan-out Scheduling<br />Scheduler<br />Scheduler<br />Scheduler<br />Scheduler<br />Scheduler<br />Scheduler<br />Scheduler<br />
  97. 97. var d = scheduler.Schedule(42, (s, x) => {<br />var d1 = s.Schedule(x + 1, Console.WriteLine);<br />var d2 = s.Schedule(x + 2, Console.WriteLine);<br />});<br />Fan-out Scheduling<br />How do we make d depend on d1 & d2?<br />
  98. 98. interfaceIScheduler {<br /> …<br />IDisposable Schedule<T>(T state,<br />Func<IScheduler, T, IDisposable> work);<br /> …<br />}<br />Scheduler Interface Rererevisited<br />
  99. 99. var d = scheduler.Schedule(42, (s, x) => {<br />var d1 = s.Schedule(x + 1, Console.WriteLine);<br />vard2 = s.Schedule(x + 2, Console.WriteLine);<br /> return newCompositeDisposable(d1, d2);<br />});<br />Fan-out Scheduling<br />
  100. 100. scheduler.Schedule(42, (state, self) =><br /> {<br />Console.WriteLine(state);<br /> self(state + 1); });<br />Easy Recursive Scheduling<br />
  101. 101. Change Program.Main to use the AppDomainScheduler<br />ReimplementGenerateObservable.Subscribe<br />Challenge: AppDomains<br />
  102. 102. Answer<br />
  103. 103. Continuations Everywhere<br />continuation-passing style used elsewhere<br />
  104. 104. Ruby<br />1..10.each do |x| puts x * xend<br />
  105. 105. AJAX<br />$.ajax({<br /> url: 'http://en.wikipedia.org/w/api.php',<br />dataType: 'jsonp',<br />data: {<br /> action: 'opensearch',<br /> search: term,<br /> format: 'json'<br /> },<br />success: function(msg) {<br /> alert('Data saved:' + msg);<br />}<br />});<br />
  106. 106. node.js<br />var net = require('net');<br />var server = net.createServer(function (socket) {<br />socket.write("Echo serverrn"); socket.pipe(socket);<br />});<br />server.listen(1337, "127.0.0.1");<br />
  107. 107. Challenge<br />Using Rx, build a TCP server that works in a similar manner to node.js.<br />
  108. 108. The Reactive Extensions<br />Rx is …<br />a set of types representing asynchronous data streams<br />a set of operators to query asynchronous data streams<br />a set of types to parameterize concurrency<br />Rx = Observables + LINQ + Schedulers<br />
  109. 109. Learn More<br />Resources<br />Rx Developer Center<br />Rx on Channel 9<br />Projects<br />ReactiveUI<br />Fluent State Observer<br />Reactive ETL<br />ReactiveOAuth<br />Reactive Remoting<br />Extensions to the Extensions<br />Reactive Extensions – Extensions<br />Rx Contrib<br />RxUtilities<br />Rx Power Toys<br />

×