订阅和观察有什么区别

我刚刚发现了 SubscribeOn,这让我怀疑我是否应该使用它而不是 ObserveOn。谷歌给了我 给你给你,但两者都没有帮助我理解其中的区别: 它似乎难以置信的微妙。

(在我的上下文中,我有一个非 GUI 线程上的事件‘浮现’,在使用事件数据更新控件之前,我需要切换到 GUI 线程)。

21123 次浏览

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.

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.

The differences basically is that subscribeOn force the whole pipeline to be processed by another thread, but with observerOn only the steps in your pipeline define after observerOn will run in another thread only after you set it will be executed in another thread.

    Observable.just(1)
.map ---> executed in io thread
.filter ---> executed in io thread
.subscribeOn(Scheduers.io)
.subscribe()

All the steps of the pipeline will be executed in another thread.

 Observable.just(1)
.map ---> executed in Main thread
.filter ---> executed in Main thread
.observerOn(Scheduers.io)
.map ---> executed in New thread
.filter ---> executed in New thread
.subscribe()