#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.
- Did you know Task.ToObservable() and SelectMany(IO<S>, Func<S, Task<R>>) introduce concurrency? https://rx.codeplex.com/workitem/48 @ReactiveX
- Did you know that sometimes your IScheduler is essentially ignored by internal Rx optimizations? https://rx.codeplex.com/workitem/10 @ReactiveX
- 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
- 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
- Calling a function is "active", being a function is "reactive". It's a dual perspective. Rx captures the concept in a type. #Monad
- Did you know RefCount might be the wrong choice? Try the Publish / PublishLast / Replay overloads with a selector parameter instead.
- Did you know ObserveOn operators often add unnecessary overhead? Use the parameterized scheduling of general query operators instead.
- Did you know that nested observables are generally hot? You must subscribe while in the call to OnNext or risk missing notifications.
- Scheduling is viral. In a library, offer an IScheduler parameter when defining a query with operators that parameterize scheduling.
- GroupJoin is the operational basis for many queries: GroupJoin + SelectMany = Join; GroupJoin > Window; Window + ToList = Buffer
- Did you know that you can await observables to get the last value? Just be sure that it terminates with OnCompleted or OnError.
- SelectMany = Select(x=>IO).Merge(); So, to concatenate terminating sequences rather than merging, simply use Select(x=>IO).Concat();
- Never call OnNext concurrently in Create, Subjects or ObserverBase. Breaks the Rx contract and may cause threading bugs in operators.
- Never call OnNext in a try..catch statement in your Observable.Create func. §6.4 Note 2, Rx Design Guidelines
- Avoid closing over local variables with Observable.Create; you probably didn't intend for all subscribers to share the same state.
- C# doesn't support async iterators natively, though Observable.Create provides overloads for defining an iterator with async/await.
- Think about reentry when defining new operators; be sure to protect SerialDisposable with double indirection when calling Subscribe.
- 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
- To define a complex query, start by breaking it down first into simple individual observables, then compose them together. #Abstract
- When cardinality = 1, Task<T> is often a better model than IObservable<T>. ToTask or `await` provide useful conversions if needed.
- Get in the habit of calling SubscribeSafe when writing operators with Observable.Create, and nowhere else. Rx Blog Link
- Publish makes a cold observable hot. Defer makes a hot observable cold. http://davesexton.com/blog/post/Hot-and-Cold-Observables.aspx
- 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)
- 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
- 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
- Always consider using GroupByUntil instead of GroupBy to avoid memory leaks on non-terminating observables with terminating key data.
- 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.
- CurrentThreadScheduler doesn't refer to the thread at the time of subscription, it refers to any thread at the time of notification.
- Liberal use of the Do operator to log values makes debugging a whole lot easier. Use conditional compilation to disable for release.
- Beware of mutable state in notifications. Always consider cloning or wrapping objects in a read-only interface to avoid contention.
- Order of subscriptions != order of observations, except specific hot observables like Publish, PublishLast, Replay, FromEvent, etc.
- The Retry operator is often incorrect; consider using RetryConsecutive(count, backOffSelector) instead: Source-Link #Rxx
- Try to avoid side effects in queries except within the Do operator or Subscribe. Pure queries are much easier to read and to change.
- Passing a scheduler directly to an overloaded operator instead of ObserveOn generally avoids extra, unnecessary context switches.
- Rx is free-threaded and generally relies on asynchrony rather than concurrency. This makes the best use of limited system resources.
- The Scan operator provides a way to be stateful inside a query without a closure. Works great for simple parsing and state machines.
- Recursive observables like While, DoWhile and Repeat cannot be canceled unless the source introduces asynchrony or concurrency.
- Use n-ary Zip to join the results of a "fork join". Use task.ToObservable, xs.PublishLast, Start, StartAsync, etc. to make "forks".
- In Create, never catch exceptions from calls to OnNext, OnError or OnCompleted §6.4 Note, Rx Design Guidelines
- The Amb op can be used to converge decision branches: from _ in trySend(msg) from res in successes.Amb(failures) select Sent(msg,res)
- AsObservable is useful for hiding the identity of an observable, like a Subject, and for breaking out of an IQbservable<T> context.
- 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
- SubscribeOn is almost exclusively useful for thread-affine subscription, which is rare. You probably wanted to use ObserveOn instead.
- The Catch overload with TException is better than the overloads without. The same principal applies in imperative try...catch blocks.
- Passing an OnError handler to Subscribe is generally wrong. An app is unlikely to recover. Consider applying Retry or Catch instead.
- CombineLatest has "when any" semantics. It's useful for merging property changes of different objects to form "behaviors" in a GUI.
- Zip has "when all" semantics. It's useful for joining different events without filtering, such as visiting the steps of a wizard GUI.
- N-ary operators: Merge Concat Switch Amb Catch OnErrorResumeNext CombineLatest Zip. But only the first 3 are IO<IO<T>>! #RxMissingOps
- Windows (inner observables) are hot. Subscribe or risk missing notifications. Alt: Apply n-ary Merge or Switch to outer observable.
- (#50) A good new year's resolution "I will help others learn to tame concurrency with Rx!" Archive: [Link to this page] @ReactiveX
- When using Create+IScheduler, schedule the whole computation, not only the observations
s.Schedule(()=>{ x=Compute(); o.OnNext(x); })