我刚刚发现SubscribeOn
,这使我想知道是否应该使用它而不是ObserveOn
。Google在这里和这里带走了我,但两者都没有帮助我改变这种差异:这似乎难以置信。
(在我的上下文中,我在非GUI线程上有事件“即将来临”,在使用事件数据更新控件之前,我需要切换到GUI线程)。
Answers:
通过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
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更新)。所以你想在GUI线程上观察。
根本上的区别在于,subscribeOn强制整个管道由另一个线程处理,但是使用observerOn,只有在您设置管道将在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()
SubscribeOn
解决了以下问题:从Winforms或WPF中的多个线程添加事件处理程序会导致异常。