Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between cold observable in RX and normal Enumerable

I am new to Rx. I can see some real benefits of using Hot Observables, however I was recently asked the question on what the difference was between a cold observable and an equivalent enumerable (see code snippet below)...

    var resRx = Observable.Range(1, 10);
    var resOb = Enumerable.Range(1, 10);

Can anyone explain very simply what the difference is between the two and what benefit I would get from the cold observable vs the enumerable.

like image 627
Mark Pearl Avatar asked Aug 27 '11 14:08

Mark Pearl


People also ask

What is the difference between and hot and cold observable?

There are two types of observables: hot and cold. The main difference is that a cold observable creates a data producer for each subscriber, whereas a hot observable creates a data producer first, and each subscriber gets the data from one producer, starting from the moment of subscription.

Which of the following is an example of a hot observable?

A typical example of a hot observable are mousemove events. The mouse moves happen regardless if someone is listening or not. When we start listening for them, we only get future events. Cold Observables on the other hand are the lazy ones.

Is subject hot or cold?

The Subject itself is hot/shared.


2 Answers

There are several differences between the two.

Who controls the 'enumeration'

With the observable (hot or cold), it is the observable that determines when and on what thread the values are returned. An enumerable on the other hand gets each value when you request it and is processed on the thread requesting the enumeration.

Code Flow

Processing enumerables is typically done in a for each loop (or occasionally getting the enumerator and using a while loop). Your code will typically process all values before continuing. Observables require a callback. Blocking further execution of your code (say to keep from exiting a console app) requires extra code on your part. There are some blocking operators for observables, such as First, but they are the exception rather than the rule for normal usage.

Take this trivial sample program as an example. With the enumerable, all the values get written before continuing on to the next part. The values from the observable, however, are not guaranteed to ever be written. How many values gets written before the program terminates is pretty much a race condition.

static void Main(string[] args)
{
    var xs = Enumerable.Range(1, 10);
    foreach (var x in xs)
    {
        Console.WriteLine(x);
    }
    //at this point, all values have been written

    var ys = Observable.Range(1, 10);
    ys.Subscribe(y => Console.WriteLine(y));
    //at this point, no values have been written (in general)

    //either add a Console.ReadKey or some sort of wait handle that
    //is set in the OnCompleted of the observer to get values
}

Asynchronous processes

Much like you have to write extra code to block and wait for an observable, writing an IEnumerable that uses an asynchronous process requires some extra work. Here is where the difference between the two really comes into play.

For example, in an application I am currently working on, I need to search for devices that may be attached to a serial port. An IObservable is a good fit for this because it allows me to take a callback and notify the application for each device whenever I find it without having to block and when the operation is complete. This observable qualifies as a cold observable because it will not push data out unless there is a subscriber, and each subscription gets all the results. (Unlike the typical cold observable, I start the work before a subscription, but no data is lost because it gets buffered into a replay subject.) However, it would not make much sense to me to convert it to an Enumerable because of the asynchronous nature.

like image 184
Gideon Engelberth Avatar answered Oct 13 '22 23:10

Gideon Engelberth


Almost all Enumerables that you are used to are "Cold" Enumerables? Why? Because if you were to ForEach over the Enumerable.Range twice, you'd get 2x the numbers.

If Enumerable.Range were a Hot Enumerable, it would only give you the list once and the 2nd ForEach would just be empty.

For Rx, a Cold Observable means that every time you call Subscribe (the equivalent of ForEach in Rx), you'll receive a new list of stuff. Hot Observables like FromEvent aren't going to give you a new stream of events every time you Subscribe, it's just going to be another connection to the same event stream.

What's the advantage of Rx here though? Being able to convert that range into async requests:

IObservable<Image> fetchImageByIndex(int imageIndexOnSite);

Observable.Range(0, 10)
    .SelectMany(x => fetchImageByIndex(x)) 
    .Subscribe(image => saveImageToDisk(image));
like image 44
Ana Betts Avatar answered Oct 13 '22 21:10

Ana Betts