简体   繁体   中英

Why my binding does not update without SubscribeOn/ObserveOn?

I am refactoring some code.

Can someone tell me why does my binding in the viewModel stop updating if I comment out those two lines:

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

How come it affect the second subscribe?

RendererService.WhenRenderProgress.Subscribe

My goal is to remove the wrapper Observable.Create(observer... but when I comment it out, even if the subject emit values, the viewModel does not render them.

Thank you!

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);
        });
    }
}

EDIT:

Sorry, your comments make sense. It is due to WPF threading requirements. The second subscribe has to happen on the UI thread. The best way for that to happen is to change this line...

    RendererService.WhenRenderProgress.Subscribe(i =>

to this...

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

Once you make that change, you can remove the SubscribeOn and ObserveOn calls by the first subscription.

All this happens because Reactive IObservables don't care which thread they're observed on. If your event starts on a background thread, and all the operators are synchronous (which they are here), then it will be observed on the same thread.


The way you have it laid out, this is impossible to reproduce.

If I had to guess, I would guess that there's some exception being thrown in the .Render function, that blows up the first subscription. Since there's no other subscription, the rest of the Observable.Create never happens, since observables only do stuff when there is at least one subscription. The second subscription isn't subscribed to the producing observable, it's listening to a side-effect.

I would recommend you try changing the first subscription call from

    .Subscribe();

to

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

or something like that. This way you can see what's going wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM