#RxTip Tweets Archive

See my latest #RxTip tweets...


I try to tweet useful tips related to Rx theory and practice that don't just repeat what has already been stated in the Rx Design Guidelines, with a couple of notable exceptions that I feel are important enough to be restated. I've already tweeted the following tips, newest on bottom, with the hashtag #RxTip. Enjoy.

  1. Did you know Task.ToObservable() and SelectMany(IO<S>, Func<S, Task<R>>) introduce concurrency? https://rx.codeplex.com/workitem/48 @ReactiveX
  2. Did you know that sometimes your IScheduler is essentially ignored by internal Rx optimizations? https://rx.codeplex.com/workitem/10 @ReactiveX
  3. Did you know as of Rx 2.2 you can use BehaviorSubject.Value to extract? Makes a good backing field https://rx.codeplex.com/workitem/8 @ReactiveX
  4. Attempting to vary static args on buffered ops like Merge(max) loses data https://rx.codeplex.com/workitem/43 https://rx.codeplex.com/workitem/44 @ReactiveX
  5. Calling a function is "active", being a function is "reactive". It's a dual perspective. Rx captures the concept in a type. #Monad
  6. Did you know RefCount might be the wrong choice?  Try the Publish / PublishLast / Replay overloads with a selector parameter instead.
  7. Did you know ObserveOn operators often add unnecessary overhead? Use the parameterized scheduling of general query operators instead.
  8. Did you know that nested observables are generally hot? You must subscribe while in the call to OnNext or risk missing notifications.
  9. Scheduling is viral. In a library, offer an IScheduler parameter when defining a query with operators that parameterize scheduling.
  10. GroupJoin is the operational basis for many queries: GroupJoin + SelectMany = Join; GroupJoin > Window; Window + ToList = Buffer
  11. Did you know that you can await observables to get the last value? Just be sure that it terminates with OnCompleted or OnError.
  12. SelectMany = Select(x=>IO).Merge(); So, to concatenate terminating sequences rather than merging, simply use Select(x=>IO).Concat();
  13. Never call OnNext concurrently in Create, Subjects or ObserverBase. Breaks the Rx contract and may cause threading bugs in operators.
  14. Never call OnNext in a try..catch statement in your Observable.Create func. §6.4 Note 2, Rx Design Guidelines
  15. Avoid closing over local variables with Observable.Create; you probably didn't intend for all subscribers to share the same state.
  16. C# doesn't support async iterators natively, though Observable.Create provides overloads for defining an iterator with async/await.
  17. Think about reentry when defining new operators; be sure to protect SerialDisposable with double indirection when calling Subscribe.
  18. If you don't know the temperature of an observable, then you must assume that it's cold. http://davesexton.com/blog/post/Hot-and-Cold-Observables.aspx
  19. To define a complex query, start by breaking it down first into simple individual observables, then compose them together. #Abstract
  20. When cardinality = 1, Task<T> is often a better model than IObservable<T>.  ToTask or `await` provide useful conversions if needed.
  21. Get in the habit of calling SubscribeSafe when writing operators with Observable.Create, and nowhere else. Rx Blog Link
  22.  Publish makes a cold observable hot. Defer makes a hot observable cold. http://davesexton.com/blog/post/Hot-and-Cold-Observables.aspx
  23. Scoping to an object's lifetime: Define queries in an iterator block, yield subscriptions and collect them into a CompositeDisposable
    (Follow-up tweet upon request: https://gist.github.com/RxDave/39b7eeff79b57761b14a)
  24. Avoid Subject<T> unless you need a .NET event-like observable on a class and you've got no convertible sources http://davesexton.com/blog/post/To-Use-Subject-Or-Not-To-Use-Subject.aspx
  25. Subscribing to IQbservable sends entire query to a push service. Avoids complex parameters and query strings. http://davesexton.com/blog/page/TCP-Qbservable-Provider-Series.aspx
  26. Always consider using GroupByUntil instead of GroupBy to avoid memory leaks on non-terminating observables with terminating key data.
  27. Rx isn't just an API, it's a language. It has a grammar, operators, correct and incorrect syntax, and it's an abstraction over LINQ.
  28. CurrentThreadScheduler doesn't refer to the thread at the time of subscription, it refers to any thread at the time of notification.
  29. Liberal use of the Do operator to log values makes debugging a whole lot easier. Use conditional compilation to disable for release.
  30. Beware of mutable state in notifications. Always consider cloning or wrapping objects in a read-only interface to avoid contention.
  31. Order of subscriptions != order of observations, except specific hot observables like Publish, PublishLast, Replay, FromEvent, etc.
  32. The Retry operator is often incorrect; consider using RetryConsecutive(count, backOffSelector) instead: Source-Link #Rxx
  33. Try to avoid side effects in queries except within the Do operator or Subscribe. Pure queries are much easier to read and to change.
  34. Passing a scheduler directly to an overloaded operator instead of ObserveOn generally avoids extra, unnecessary context switches.
  35. Rx is free-threaded and generally relies on asynchrony rather than concurrency. This makes the best use of limited system resources.
  36. The Scan operator provides a way to be stateful inside a query without a closure. Works great for simple parsing and state machines.
  37. Recursive observables like While, DoWhile and Repeat cannot be canceled unless the source introduces asynchrony or concurrency.
  38. Use n-ary Zip to join the results of a "fork join". Use task.ToObservable, xs.PublishLast, Start, StartAsync, etc. to make "forks".
  39. In Create, never catch exceptions from calls to OnNext, OnError or OnCompleted §6.4 Note, Rx Design Guidelines
  40. The Amb op can be used to converge decision branches: from _ in trySend(msg) from res in successes.Amb(failures) select Sent(msg,res)
  41. AsObservable is useful for hiding the identity of an observable, like a Subject, and for breaking out of an IQbservable<T> context.
  42. Vote for new QCS keywords in C#/VB: User Voice Link from x in xs zip y in ys do Log.Write($"{x},{y}") select new {x,y} take 5
  43. SubscribeOn is almost exclusively useful for thread-affine subscription, which is rare. You probably wanted to use ObserveOn instead.
  44. The Catch overload with TException is better than the overloads without. The same principal applies in imperative try...catch blocks.
  45. Passing an OnError handler to Subscribe is generally wrong. An app is unlikely to recover. Consider applying Retry or Catch instead.
  46. CombineLatest has "when any" semantics. It's useful for merging property changes of different objects to form "behaviors" in a GUI.
  47. Zip has "when all" semantics. It's useful for joining different events without filtering, such as visiting the steps of a wizard GUI.
  48. N-ary operators: Merge Concat Switch Amb Catch OnErrorResumeNext CombineLatest Zip. But only the first 3 are IO<IO<T>>! #RxMissingOps
  49. Windows (inner observables) are hot. Subscribe or risk missing notifications. Alt: Apply n-ary Merge or Switch to outer observable.
  50. (#50) A good new year's resolution "I will help others learn to tame concurrency with Rx!" Archive: [Link to this page] @ReactiveX
  51. When using Create+IScheduler, schedule the whole computation, not only the observations
    s.Schedule(()=>{ x=Compute(); o.OnNext(x); })