C# 我应该使用dispatcher.Invoke(…)还是ObserveOn(dispatcher)?

C# 我应该使用dispatcher.Invoke(…)还是ObserveOn(dispatcher)?,c#,system.reactive,reactiveui,C#,System.reactive,Reactiveui,我已经得到了一些代码来处理在其构造函数中将调度器传递给视图模型的位置。我现在想知道,当我希望在UI线程上执行某些操作时,是应该使用ObserveOn(dispatcher)还是dispatcher.Invoke(…) 例如,我可以这样做: this.WhenAny(me => me.SomeValue, _ => Unit.Default) .ObserveOn(dispatcher) .Subscribe(_ => SomeMethod()); ... private v

我已经得到了一些代码来处理在其构造函数中将调度器传递给视图模型的位置。我现在想知道,当我希望在UI线程上执行某些操作时,是应该使用
ObserveOn(dispatcher)
还是
dispatcher.Invoke(…)

例如,我可以这样做:

this.WhenAny(me => me.SomeValue, _ => Unit.Default)
.ObserveOn(dispatcher)
.Subscribe(_ => SomeMethod());

...

private void SomeMethod()
{
    //do some stuff
}
this.WhenAny(me => me.SomeValue, _ => Unit.Default)
.Subscribe(_ => SomeMethod());
或者我可以这样做:

this.WhenAny(me => me.SomeValue, _ => Unit.Default)
.ObserveOn(dispatcher)
.Subscribe(_ => SomeMethod());

...

private void SomeMethod()
{
    //do some stuff
}
this.WhenAny(me => me.SomeValue, _ => Unit.Default)
.Subscribe(_ => SomeMethod());
这意味着我可以这样做:

private void SomeMethod()
{
    dispatcher.Invoke(new Action(() =>{//do some stuff});
}
这两者之间有什么主要区别吗

我关心的是,如果我想在代码中的其他部分调用SomeMethod(),这不是由某个值更改触发的,该怎么办?然后我需要执行
dispatcher.invoke(新操作(()=>someMethod())
,这使我认为在SomeMethod中使用
dispatcher.Invoke(…)
是最好的选择


这是一个好的举措还是一个坏的举措?目前,我正在均衡地使用这两种技术。我打算换一种,但首先想知道正确的方法。

功能上没有区别。但是,我会使用
ObserveOn(dispatcher)
并保持
SomeMethod()
不变。您以后也可能从UI线程调用
SomeMethod()
,在这种情况下,调度是不必要的。我想说,调用代码应该负责知道它是否在UI线程上运行,因此是否需要调度。

我想看看是否可以给我一个
IScheduler
的实例,它是
DispatchersScheduler
的一个实现。这样,我就可以使用
TestScheduler
测试我的代码,而不必进入调度器的内部并推动帧等。一旦你有了
IScheduler
的实例,你就可以用它来
ObserveOn(dispatcherScheduler)

我也同意@mclaassen的观点,即您应该知道自己在哪个调度程序/线程上,因此是否需要调度程序/调用。例如,如果您正在观察
INotifyPropertyChanged
事件,那么您将在调度程序上,因此无需调度。如果您收到来自网络呼叫或繁重计算的响应,那么您可能在另一个线程上,因此您应该安排/调度以返回调度程序。成本

Rx中的标准模式是不执行调度,因为您已经在正确的线程上:

//this is a ViewModel, and property changes occur on the dispatcher
this.WhenAny(
    vm => vm.PropertyA, 
    vm => vm.PropertyB, 
    _ => Unit.Default)
.Subscribe(_ => SomeMethod());
或者,应用
SubscribeOn
/
ObserveOn
模式退出当前线程,执行工作,然后在原始线程上接收结果

myRepo.GetDataFromNetwork()
    .SubscribeOn(taskPoolScheduler)
    .ObserveOn(dispatcherScheduler)
    .Subscribe(_ => SomeMethod());

我想说这是一个有趣的问题,如果您有反应式扩展,并且不需要在任何其他地方调用(),为什么不使用这些扩展呢?这就是为什么它会在那里。如果合适/合理,请稍后重新考虑。在此处再添加一点。。。在自定义方法中使用调度程序会完全破坏SRP,也会使测试更加困难。方法应该设计成做一件事,而不知道应该在哪里做。这就是可观察的组合和编排的目的。此外,如果代码中有多个地方调用此方法,只需重新路由该代码,使其使用原始调度即可。这就是为什么我们有像
Merge
这样的操作符。这给了我们更多的细粒度控制。对此,使用ObserveOnTo Christopher Harris对SRP的评论,测试Rx代码要容易得多。一些运营商需要调度,在这种情况下,他们应该将调度程序作为参数。同样,Christopher的评论,我不建议这里的任何地方,这应该是一个自定义运营商。这只是一种模式。