Rx Hands-On Labs published

Hi folks,

Yesterday, we released two hands-on labs on Rx both for .NET and for JS. The goal of those two documents is to present the reader with a gentle introduction into the subject, based on a series of incremental samples. This is based on a series on internal presentations we gave on the subject, being extended to various upcoming internal training events. Obviously we like to share this with the community, so here are the pointers:

Enjoy! As usual, all feedback is welcome. The idea is to evolve those documents based on feedback from different channels.

Please note that the example of Generate on page 9 of the .NET version is based on the upcoming release of Rx in which we have changed the order of the arguments to match the for-loop construct.

Until that release is available, replace
    IObservable<int> source = Observable.Generate(0, i => i < 5, i => i + 1, i => i * i);
   IObservable<int> source = Observable.Generate(0, i => i < 5, i => i * i, i => i + 1);


[Edit 7/15/2010]

Hi folks,

We really appreciate the active feedback. Some suggestions have been incorporated now. The links have been updated to refer to the new documents that have the changes applied.



Comments (26)

  1. In exercise 2 step 4 you have the following line:

    IObservable<int> source = Observable.Generate(0, i => i < 5, i => i + 1, i => i * i);

    However, it generates an infinite output, instead it should be:

    IObservable<int> source = Observable.Generate(0, i => i < 5, i => i * i, i => i + 1);

    It seems the iterator and the result selector has been switched.

  2. Sorry… Excercise 2 step 7 that is… I guess we all make mistakes. 😉

  3. Rx JS HOL, page 27 says that

      "function (term) { return searchWikipedia(term); }"

    eta-reduces to


    but that should be "searchWikipedia" instead.

  4. Jeffrey van Gogh says:

    Johannes, see the comment regarding Generate at the end of the blog post….

  5. On page 22,  the custom time stamp operator:

           public static IObservable<T> LogTimestampedValues<T>(this IObservable<T> source, Action<T> onNext)


               return source.Timestamp().Do(onNext).RemoveTimestamp();


    Should be:

    public static IObservable<T> LogTimestampedValues<T>(this IObservable<T> source, Action<Timestamped<T>> onNext)


               return source.Timestamp().Do(onNext).RemoveTimestamp();


    Great document, great framework… keep up the brilliant work!

  6. Hi,

    congratulations to this HOL. That's how documentation should look like!

  7. msuser-ngm says:

    This is terrific! I hope you guys will write more of these to cover advanced topics… but if not, this is still best documentation so far for Rx! Thanks.

  8. This is exactly the kind of thing I was looking for to get off the ground with RX. Thanks Bart and RX team!

  9. Looks like an excellent intro so far!

    Minor typo (pg 7):

     s/different form/different from/

  10. John Lewicki says:

    This was a very well done tutorial; very helpful avoiding getting lost in the sea of available Observable combinators.  More please!

  11. Exercise 2, step 9:

    Observable.Run returns void, but the example expects an "IDisposable subscription" return value.

  12. Excercise 2, step 10's parameter order appears to also be based on the yet unreleased version of reactive extensions.

  13. [Apologies if this is a duplicate, I received no success message the first time I clicked "Post".]

    Excercise 5, step 4:

    It seems better to .Throttle(…) *before* .DistinctUntilChanged().

    With the order in the HOL, .DistinctUntilChanged() observes every typed value making it possible to get consecutive non-distinct notifications: Type "reactive" and wait for it to appear. Type backspace then 'e' within the throttle duration. Notice that "reactive" is displayed a second time. In the hypothetical spell-check application, this represents an unnecessary server call.

    If, however, .Throttle(…) is called first, .DistinctUntilChanged() only gets a chance to observe potentially submitted values. Consecutive duplicate values are not possible.

  14. Excercise 8, step 5:

    After discussing the confusing cardinality of the webservice output (the webservice returns an array of words), the query shown in step five confuses the cardinality of the webservice output by naming the query range variable "word" [singular] rather than "words" or "wordList" [plural].

  15. The first Windows Forms Rx sample does not work for me (page 14).

    … moves.Subscribe(…) … // blocked the UI

    I tried changing the current SynchronizationContext using SynchronizationContexts.WindowsForms but that didn't help either.

    Then I Intellisensed my way into SubscribeOnWindowsForms. That didn't work at first either. Only when supplying the actual form did it work without blocking the UI thread.

    … moves.SubscribeOnWindowsForms(frm).Subscribe(…) …

    what did I miss? 🙂

    – Bent

  16. home jobs says:

    I like your information. I have been looking for this type of information interesting and good

  17. Vinay says:

    Excellent job! One of the best documentation/explanations I have ever seen.. Kudos to the team

  18. stejcz says:

    Thx for this intro!

    As for js version: "If desired, clean-up of the event handler can be taken care of by calling Dispose on the object returned by the toObservable operator."

    I suppose Dispose should be called on object returned from Subscribe, not toObservable

  19. Ali Bazzi says:

    Very nice work (For the Framework and Document also … )

    I Appreciate the People Behind this Terrific Framework , Go Microsoft Research Go !

  20. I just want to let you guys know I *heart* Rx. 🙂

  21. Julian Ashworth says:

    Excellent intro. Can we have a "303" on some of the topics mentioned in the "202", e.g. more on error handling, .Publish, etc.

  22. R Warder says:

    Page 14, 3.4, am getting an exception:

    A first chance exception of type 'System.EntryPointNotFoundException' occurred in System.Reactive.dll


    Any ideas?

  23. R Warder says:

    My mistake.  Had an older Rx installed.  Uninstalled both and reinstalled and all good.

  24. James says:

    One of the best HOLs I've ever seen. Well thought out, flows nicely.

  25. Akhil Deshpande says:

    if the subscription order is guaranteed, why do the output of the sample code below differ? My understanding was that both subscriptions should have produced the same result. Am I doing something wrong?

       public class A02BufferAndWindowEx


           internal static void Run()


               var numbers = Enumerable.Range(1, 26);

               Console.WriteLine("Take the input in buffer size of 10");

               var buffNumbers = numbers.ToObservable().Buffer(10);





           private static void Print(IEnumerable<int> nums)



               Console.Write("Buffer size: " + nums.Count() + "tItems: ");



           private static void PrintSingle(int num)


               Console.Write(" " + num);


           private static void Print2(IEnumerable<int> nums)



               Console.Write("Buffer size: " + nums.Count() + "tItems: ");

               foreach (var num in nums)






  26. Andy says:

    This HOL seems to be very out of date, e.g. System.CoreEx.dll no longer exists, and methods like subscriber.Run and Observable.GenerateWithTime have been removed. Can we have an updated HOL please?!