为什么没有SubscribeOn / ObserveOn我的绑定不会更新?

时间:2018-04-26 19:36:57

标签: c# wpf system.reactive caliburn.micro

我正在重构一些代码。

如果我注释掉这两行,有人可以告诉我为什么我在viewModel中的绑定会停止更新:

.SubscribeOn(ThreadPoolScheduler.Instance)
.ObserveOn(Application.Current.Dispatcher)

它如何影响第二次订阅?

RendererService.WhenRenderProgress.Subscribe

我的目标是删除包装器Observable.Create(observer ...但是当我将它注释掉时,即使主题发出值,viewModel也不会呈现它们。

谢谢!

public class RendererService
{
    public Subject<int> WhenRenderProgress = new Subject<int>();
    public void Render()
    {
        Observable.Create<Unit>(observer =>
        {
            for (var i = 0; i < 100; i++)
            {
                WhenRenderProgress.OnNext(i);
            }
            observer.OnCompleted();
            return Disposable.Empty;
        })
        .SubscribeOn(ThreadPoolScheduler.Instance)
        .ObserveOn(Application.Current.Dispatcher)
        .Subscribe();
    }
}

public class ViewModel: Screen, IViewModel, IDisposable
{
    public int Progress { get; set; } 
    public ViewModel(RendererService RendererService)
    {
        RendererService.WhenRenderProgress.Subscribe(i =>
        {
            Progress = i;
            NotifyOfPropertyChange(() => Progress);
        });
    }
}

1 个答案:

答案 0 :(得分:0)

修改

抱歉,您的评论很有意义。这是由于WPF线程要求。第二个订阅必须在UI线程上进行。发生这种情况的最佳方法是改变这一行......

    RendererService.WhenRenderProgress.Subscribe(i =>

到此......

    RendererService.WhenRenderProgress.ObserveOn(Application.Current.Dispatcher).Subscribe(i =>

进行更改后,您可以通过首次订阅删除SubscribeOnObserveOn来电。

这一切都发生了,因为Reactive IObservable并不关心他们观察到的线索。如果您的事件在后台线程上启动,并且所有操作符都是同步的(它们在这里),那么它将在同一个线程上被观察到。

你的方式布局,这是不可能重现的。

如果我不得不猜测,我猜想.Render函数中会抛出一些异常,这会导致第一次订阅失败。由于没有其他订阅,Observable.Create的其余部分永远不会发生,因为observable只在至少有一个订阅时执行。第二个订阅不是订阅到生产的观察者,它正在听取副作用。

我建议您尝试从

更改第一个订阅电话
    .Subscribe();

    .Subscribe(item => {}, e => LogException(e));

或类似的东西。这样你就可以看出出了什么问题。