20

Both the System.Reactive extension for .NET and new C# 5.0 (.NET 4.5) async/await pursue (or based on) future and promises constructs paradigm (approach).

Can you give the (*) simplest C# code example illustrating the difference between them?

(*)
Is it possible without I/O, internet or database connections?

Update:
Well, let me reformulate if this question seemed to be answered before.
Why would one add and start using Reactive (Rx) extensions for .NET while using native .NET Iobservable/IObserver + await/async?

What are the possible illustrations of what one will be missing from Rx that made to do the same more clumsy or less efficient without Rx (i.e. engaging just native .NET Iobservable/IObserver + await/async approach)?

3 Answers3

21

The Future/Promise paradigm generally is used for returning a single value in the future. Perhaps there is some heavy calculation or IO that is required and hence why it can not be guaranteed to be return synchronously in a timely manner.

Rx (and by proxy the IObserver<T>/IObservable<T> interfaces) is a paradigm of observable sequences. Just as a synchronous method could return a single value (int), it could also return an IEnumerable<int> with one value. Comparing this to an asynchronous world, Task<int> can return a single int value, IObservable<int> could return a sequence with just one int value.

So if you wanted to return a sequence of values with Task<T>, you would have to either create some sort of continuation, or return a collection/array/list of values as the T e.g. Task<int[]>. This however will mean you get all or non of the values.

Task/Task<T> is also a concrete type, where as Rx uses interfaces to abstract you from implementation. I have found this to help in unit testing. TaskCompletionSource<T> however can be helpful to avoid implicit concurrency when testing with tasks.

Finally, besides the main difference that Rx is dealing with sequences of values (not single values), Rx is also designed to work with LINQ to deliver the querying and composition benefits that seems to work very well with sequences (either at rest like IEnumerable<T>, or in motion like IObservable<T>).

Ultimately these are different tools for slightly different jobs. There is some overlap, so you sometimes can use one to do what the other is better at. To be specific, I think Task is better at composing units of asynchronous work together (Do this, then do that, then do this), where as Rx is better at composing sequences of events together (When this event happens, do this with data from this other event).

Lee Campbell
  • 10,631
  • 1
  • 34
  • 29
  • You don't need `Task` for multiple values, for multiple values, you can use `Task>` and you can also use `INotifyCollectionChanged` interface. – Akash Kava Apr 19 '16 at 07:52
  • As pointed out "..return a collection/array/list of value..". And the discussion is not about Events (which more closely relate to RX), but about a comparison between `Rx` and `Task`. Adding events, APM, threads, callbacks and other asynchronous styles would make for a very large discussion indeed, or even a book. ;-) – Lee Campbell Apr 20 '16 at 04:47
  • “When this event happens, do this with data from this other event” that clicked on my mind really hard. I finally started getting the concept, thank you! the other day I was trying to do exactly that in React using hooks, but couldn’t figure out how to do it without sequential code, I guess I should take a look at RxJs – marcos.borunda Aug 03 '21 at 04:11
5

They're not mutually exclusive. The main determination is whether you have a single future result or multiple future results.

http://blogs.msdn.com/b/rxteam/archive/2012/03/12/reactive-extensions-v2-0-beta-available-now.aspx

http://blogs.msdn.com/cfs-filesystemfile.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-31-75-metablogapi/0815.image_5F00_thumb_5F00_59BBA077.png

James Manning
  • 13,429
  • 2
  • 40
  • 64
5

I like the table in the Reactive documentation: http://reactivex.io/intro.html

I have my own take on it where i add a third dimension non-composable/composable.

Non-composable:

       |  Single Item   | Multiple items
 ------|----------------|----------------
 Sync  | Function       | Iterable
 Async | Async function | Observable

Composable:

       |      Single Item      |       Multiple items
 ------|-----------------------|----------------------------
 Sync  | Higher order function | Linq/Ramda/java.util.stream
 Async | Future/promise        | Rx observable

And mind you that depending on the implementation, you can have futures and rx observables that can act both synchronously or asynchronously depending on whether what you are trying to do with them is synchronous or asynchrounous

Sámal Rasmussen
  • 2,887
  • 35
  • 36