我刚刚发现了SubscribeOn
,这让我想知道我是否应该使用它而不是ObserveOn
。谷歌带我here和here,但两者都没有帮我解决这个问题:看起来非常微妙。
(在我的上下文中,我在非gui线程上有'事件',我需要在使用事件数据更新控件之前切换到gui线程。)
答案 0 :(得分:54)
通过考虑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更新)。所以你想.ObserveOn GUI线程。
答案 1 :(得分:52)
前段时间我遇到了类似的问题并询问了this有关它的问题。我认为那里的回复(包括评论)会回答你的问题。总结一下:
ObserveOn
。如果您引用System.Reactive.Windows.Forms.dll
,则会获得方便的.ObserveOn(form)
。SubscribeOn
控制实际调用订阅的线程。这里解决的问题是,如果从多个不同的线程添加事件处理程序,WinForms和WPF将抛出异常。此外,this帖子对于确定ObserveOn
和SubscribeOn
之间的关系非常有帮助。
答案 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()