【问题标题】:Why my binding does not update without SubscribeOn/ObserveOn?为什么我的绑定在没有 SubscribeOn/ObserveOn 的情况下不会更新?
【发布时间】:2018-04-26 19:36:56
【问题描述】:

我正在重构一些代码。

如果我注释掉这两行,谁能告诉我为什么我在 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);
        });
    }
}

【问题讨论】:

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


    【解决方案1】:

    编辑:

    抱歉,您的 cmets 说得通。这是由于 WPF 线程要求。第二次订阅必须发生在 UI 线程上。发生这种情况的最好方法是改变这条线......

        RendererService.WhenRenderProgress.Subscribe(i =>
    

    到这个...

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

    进行更改后,您可以删除第一次订阅时的 SubscribeOnObserveOn 调用。

    所有这一切的发生都是因为反应式 IObservables 不关心它们在哪个线程上被观察到。如果您的事件在后台线程上开始,并且所有运算符都是同步的(它们在这里),那么它将在同一个线程上被观察到。


    按照您的布局方式,这是不可能重现的。

    如果我不得不猜测,我会猜测.Render 函数中抛出了一些异常,这会破坏第一次订阅。由于没有其他订阅,Observable.Create 的其余部分永远不会发生,因为 observable 仅在至少有一个订阅时才会执行操作。第二个订阅没有订阅到产生的 observable,它正在监听一个副作用。

    我建议您尝试将第一个订阅调用从

        .Subscribe();
    

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

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

    【讨论】:

    • 我放了一个断点,两种情况都命中了 NotifyOfPropertyChange(() => Progress);它只是一种情况更新 UI,而另一种不更新 UI。
    • 我想知道是否与 UI 线程 VS 后台线程有关。我对 WPF 的掌握不够。
    • 是的。更新了答案。
    • 嗯...惊喜,从第一个订阅中删除 SubscribeOn 和 ObserveOn 然后在第二个订阅上添加 .ObserveOn(Application.Current.Dispatcher) 后,我在第二个订阅中的断点停止命中,而我的OnNext(i) 命中的断点
    • 哼...我重构的代码在一个巨大的异步函数中。这会影响 Reactive.NET 的行为吗?
    猜你喜欢
    • 1970-01-01
    • 2017-12-12
    • 2021-11-12
    • 2017-04-19
    • 2013-12-10
    • 2021-02-11
    • 1970-01-01
    • 2022-07-08
    • 2022-01-14
    相关资源
    最近更新 更多