Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TPL vs Reactive Framework

When would one choose to use Rx over TPL or are the 2 frameworks orthogonal?

From what I understand Rx is primarily intended to provide an abstraction over events and allow composition but it also allows for providing an abstraction over async operations. using the Createxx overloads and the Fromxxx overloads and cancellation via disposing the IDisposable returned.

TPL also provides an abstraction for operations via Task and cancellation abilities.

My dilemma is when to use which and for what scenarios?

like image 386
Abhijeet Patel Avatar asked Mar 30 '10 03:03

Abhijeet Patel


3 Answers

The main purpose of Rx is not to provide an abstraction over events. This is just one of its outcomes. Its primary purpose is to provide a composable push model for collections.

The reactive framework (Rx) is based on IObservable<T> being the mathematical dual of IEnumerable<T>. So rather than "pull" items from a collection using IEnumerable<T> we can have objects "pushed" to us via IObservable<T>.

Of course, when we actually go looking for observable sources things like events & async operations are excellent candidates.

The reactive framework naturally requires a multi-threaded model to be able to watch the sources of observable data and to manage queries and subscriptions. Rx actually makes heavy use of the TPL to do this.

So if you use Rx you are implicitly using the TPL.

You would use the TPL directly if you wish direct control over your tasks.

But if you have sources of data that you wish to observe and perform queries against then I thoroughly recommend the reactive framework.

like image 147
Enigmativity Avatar answered Oct 05 '22 10:10

Enigmativity


Some guidelines I like to follow:

  • Am I dealing with data that I don't originate. Data which arrives when it pleases? Then RX.
  • Am I originating computations and need to manage concurrency? Then TPL.
  • Am I managing multiple results, and need to choose from them based on time? Then RX.
like image 24
Scott Weinstein Avatar answered Oct 05 '22 09:10

Scott Weinstein


Update, December 2016: If you have 30 minutes, I recommend you read Joe Duffy's first-hand account instead of my speculation. I think my analysis holds up well, but if you've found this question I highly recommend you see the blog post instead of these answers because in addition to TPL vs Rx.NET he also covers MS research projects (Midori, Cosmos).

http://joeduffyblog.com/2016/11/30/15-years-of-concurrency/


I think MS made a big mistake over-correcting after .NET 2.0 came out. They introduced many different concurrency management APIs all at the same time from different parts of the company.

  • Steven Toub was pushing hard for thread-safe primitives to replace Event (which started as Future<T> and turned into Task<T>)
  • MS Research had MIN-LINQ and Reactive Extensions (Rx)
  • Hardware/Embedded had robotics cuntime (CCR)

In the meantime many managed API teams were trying to live with APM and Threadpool.QueueUserWorkItem(), not knowing if Toub would win his fight to ship Future<T>/Task<T> in mscorlib.dll. In the end it looks like they hedged, and shipped both Task<T> and IObservable<T> in mscorlib, but didn't allow any other Rx APIs (not even ISubject<T>) in mscorlib. I think this hedge ended up causing a huge amount of duplication (more later) and wasted effort inside and outside the company.

For duplication see: Task vs. IObservable<Unit>, Task<T> vs. AsyncSubject<T>, Task.Run() vs. Observable.Start(). And this is just the tip of the iceberg. But at a higher level consider:

  • StreamInsight - SQL event streams, native-code-optimized, but event queries defined using LINQ syntax
  • TPL Dataflow - built on TPL, built in parallel to Rx, optimized for tweaking threading parallelism, not good at composing queries
  • Rx - Amazing expressiveness, but fraught with peril. Mixes 'hot' streams with IEnumerable-style extension methods, which means you very easily block forever (calling First() on a hot stream never returns). Scheduling limits (limiting parallelism) is done via rather odd SubscribeOn() extension methods, which are weirdly implicit and hard to get right. If starting to learn Rx reserve a long time to learn all the pitfalls to avoid. But Rx is really the only option if composing complex event streams or you need complex filtering/querying.

I don't think Rx has a fighting chance at wide adoption until MS ships ISubject<T> in mscorlib. Which is sad, because Rx contains some very useful concrete (generic) types, like TimeInterval<T> and Timestamped<T>, which I think should be in Core/mscorlib like Nullable<T>. Also, System.Reactive.EventPattern<TEventArgs>.

like image 24
yzorg Avatar answered Oct 05 '22 11:10

yzorg