SubscribeOn 和 ObserveOn 有什么区别

发布于 2024-12-07 02:02:29 字数 461 浏览 0 评论 0原文

我刚刚发现了 SubscribeOn,这让我想知道我是否应该使用它而不是 ObserveOn。 Google 将我带到这里和<一个href="http://www.jaylee.org/post/2011/07/24/Rx-Using-the-ObserveOn-and-SubscribeOn-operators.aspx" rel="noreferrer">此处,但是两者都没有帮助我理解其中的区别:它看起来非常微妙。

(在我的上下文中,我在非 GUI 线程上“出现”了事件,并且在使用事件数据更新控件之前我需要切换到 GUI 线程)。

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).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

宣告ˉ结束 2024-12-14 02:02:29

通过将 SubscribeOn 视为将线程设置为在链中“向上传递”,并将 ObserveOn 视为设置线程在链中“向下传递”,它帮助我理解了这一点。

订阅者线程“向上传递”和观察者线程“向下传递”

下面的代码使用您可以使用的命名线程。

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));

上面的输出是:

Subscribing on Thread1
在 Thread2 上观察 1

同样有趣的是,当您注释掉 SubscribeOn 行时,输出为:

Subscribing on Main
在 Thread2 上观察 1

因为默认情况下,订阅会“传递”正在运行的线程(此处为 Main)。然后ObserveOn“向下传递”Thread2

如果您注释掉 ObserveOn 行,则输出为:

Subscribing on Thread1
在 Thread1 上观察 1

因为我们“传递”了 Thread1 上的订阅,并且默认情况下,同一线程被“传递”并用于运行观察。

在 GUI 上下文中,为了保持响应,您希望在 GUI 线程上完成最少的工作量,但需要在 GUI 线程上完成订阅(以同步 UI 更新)。所以你想观察GUI线程。

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.

垂暮老矣 2024-12-14 02:02:29

我不久前遇到了类似的问题,并询问了这个问题。我认为那里的回复(包括评论)会回答你的问题。总结一下:

  • 如果您想更新 gui 线程上的控件,请使用 ObserveOn。如果您引用System.Reactive.Windows.Forms.dll,您将获得.ObserveOn(form),这很方便。
  • SubscribeOn 控制实际调用订阅的线程。这里解决的问题是,如果从多个不同线程添加事件处理程序,WinForms 和 WPF 将引发异常。

另外, 这篇文章对于弄清楚ObserveOnSubscribeOn之间的关系非常有帮助。

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.

陈甜 2024-12-14 02:02:29

区别主要在于 subscribeOn 强制整个管道由另一个线程处理,但使用observerOn,只有在observerOn之后定义的管道中的步骤才会在另一个线程中运行,只有在您设置后才会在另一个线程中执行。

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

管道的所有步骤都将在另一个线程中执行。

 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()

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文