SubscribeOn和ObserveOn之间有什么区别

时间:2011-09-28 06:39:28

标签: .net system.reactive

我刚刚发现了SubscribeOn,这让我想知道我是否应该使用它而不是ObserveOn。谷歌带我herehere,但两者都没有帮我解决这个问题:看起来非常微妙。

(在我的上下文中,我在非gui线程上有'事件',我需要在使用事件数据更新控件之前切换到gui线程。)

3 个答案:

答案 0 :(得分:54)

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

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

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

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 Observing 1 on Thread2

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

Subscribing on Main Observing 1 on Thread2

因为默认情况下,订阅“传递”正在运行的任何一个线程(Main这里)。然后ObserveOn“向下传递”Thread2

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

Subscribing on Thread1 Observing 1 on Thread1

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

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

答案 1 :(得分:52)

前段时间我遇到了类似的问题并询问了this有关它的问题。我认为那里的回复(包括评论)会回答你的问题。总结一下:

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

此外,this帖子对于确定ObserveOnSubscribeOn之间的关系非常有帮助。

答案 2 :(得分:5)

差异主要在于subscribeOn强制整个管道由另一个线程处理,但是只有在管理器定义后,只有在设置后才会在另一个线程中运行,只有管道管理器中的步骤才会在另一个线程中执行。 / p>

    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()
相关问题