SubscribeOn和ObserveOn之间有什么区别

Ben*_*jol 70 .net system.reactive

我刚刚发现SubscribeOn,这让我想知道我是否应该使用它而不是ObserveOn.谷歌把我带到这里这里,但都没有帮助我找到差异:它似乎非常微妙.

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

Tar*_*ran 56

它帮助我通过思考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));
Run Code Online (Sandbox Code Playgroud)

以上的输出是:

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线程.


Bor*_*ris 53

我有一段时间遇到过类似的问题并且问了这个问题.我认为那里的回复(包括评论)会回答你的问题.总结一下:

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

此外,这篇文章非常有助于弄清楚ObserveOn和之间的关系SubscribeOn.


pau*_*aul 9

根本上的区别在于,subscribeOn强制整个管道由另一个线程处理,但是使用observerOn,只有在您设置管道将在observerOn之后运行的步骤之后,才能在另一个线程中执行observerOn。

    Observable.just(1) 
              .map ---> executed in io thread
              .filter ---> executed in io thread
              .subscribeOn(Scheduers.io)
              .subscribe()
Run Code Online (Sandbox Code Playgroud)

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

 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()
Run Code Online (Sandbox Code Playgroud)