Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between SubscribeOn and ObserveOn

I just discovered SubscribeOn, which makes me wonder if I should be using that instead of ObserveOn. Google took me here and here, but neither have helped me grok the difference: it seems incredibly subtle.

(In my context, I've got events 'coming up' on a non-gui thread, and I need to switch over to a gui thread before using the event data to update controls).

like image 865
Benjol Avatar asked Sep 28 '11 06:09

Benjol


People also ask

What's the difference between observeOn or subscribeOn?

The subscribeOn works upstream so the first map is in computation thread. The first observeOn was able to change the thread to IO thread and the second observeOn changed it to Main thread. The final subscribeOn is unable to change the thread set by observeOn. observeOn works only downstream.

Is RxJava single threaded?

By default, Rx is single-threaded which implies that an Observable and the chain of operators that we can apply to it will notify its observers on the same thread on which its subscribe() method is called.

What is RX Java?

RxJava is a Java library that enables Functional Reactive Programming in Android development. It raises the level of abstraction around threading in order to simplify the implementation of complex concurrent behavior.

What is Observable just?

just method. The just() method emits its parameter(s) as OnNext notifications, and after that, it emits an OnCompleted notification.


2 Answers

It helped me to understand this by thinking of SubscribeOn as setting the thread being "passed up" the chain and ObserveOn as setting the thread "passed down" the chain.

Subscriber thread "passed up" and Observer thread "passed down"

The code below uses named threads which you can play with.

Thread.CurrentThread.Name = "Main";  IScheduler thread1 = new NewThreadScheduler(x => new Thread(x) { Name = "Thread1" }); IScheduler thread2 = new NewThreadScheduler(x => new Thread(x) { Name = "Thread2" });  Observable.Create<int>(o => {     Console.WriteLine("Subscribing on " + Thread.CurrentThread.Name);     o.OnNext(1);     return Disposable.Create(() => {}); }) .SubscribeOn(thread1) .ObserveOn(thread2) .Subscribe(x => Console.WriteLine("Observing '" + x + "' on " + Thread.CurrentThread.Name)); 

The output of the above is:

Subscribing on Thread1 Observing 1 on Thread2

It's also interesting to see that when you comment out the SubscribeOn line, the output is:

Subscribing on Main Observing 1 on Thread2

Because by default the subscription "passes up" whichever thread was running (Main here). Then the ObserveOn "passes down" Thread2.

If you instead comment out the ObserveOn line, the output is:

Subscribing on Thread1 Observing 1 on Thread1

Because we "pass up" the subscription on Thread1, and by default this same thread is "passed down" and used to run the observation.

In a GUI context, to keep things responsive you want the least amount of work done on the GUI thread but you need the subscription done on the GUI thread (to synchronise UI updates). So you want to .ObserveOn the GUI thread.

like image 148
Taran Avatar answered Oct 06 '22 15:10

Taran


I had a similar problem a while back and asked this question about it. I think the responses (including the comments) there will answer your question. To summarize:

  • If you want to update controls on a gui thread, use ObserveOn. If you reference System.Reactive.Windows.Forms.dll you get the .ObserveOn(form) which is handy.
  • SubscribeOn controls the thread on which the actual call to subscribe happens. The problem solved here is that WinForms and WPF will throw exceptions if you add event handlers from multiple different threads.

Also, this post was very helpful in figuring out the relationship between ObserveOn and SubscribeOn.

like image 30
Boris Avatar answered Oct 06 '22 16:10

Boris