Почему моя привязка не обновляется без SubscribeOn / ObserveOn? - PullRequest
0 голосов
/ 26 апреля 2018

Я рефакторинг некоторого кода.

Может кто-нибудь сказать мне, почему моя привязка в viewModel перестает обновляться, если я закомментирую эти две строки:

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

Как это повлияло на вторую подписку?

RendererService.WhenRenderProgress.Subscribe

Моя цель - удалить обертку Observable.Create (наблюдатель ... но когда я закомментирую ее, даже если объект выдает значения, 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 голосов
/ 27 апреля 2018

EDIT:

Извините, ваши комментарии имеют смысл. Это связано с требованиями потоков WPF. Вторая подписка должна происходить в потоке пользовательского интерфейса. Лучший способ для этого - изменить эту строку ...

    RendererService.WhenRenderProgress.Subscribe(i =>

к этому ...

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

После внесения этого изменения вы можете удалить вызовы SubscribeOn и ObserveOn по первой подписке.

Все это происходит потому, что Reactive IObservables не волнует, в каком потоке они наблюдаются. Если ваше событие начинается в фоновом потоке, и все операторы синхронны (что они здесь есть), то оно будет наблюдаться в том же потоке.


То, как вы это изложили, невозможно воспроизвести.

Если бы мне пришлось угадывать, я бы предположил, что в функции .Render возникает какое-то исключение, которое взрывает первую подписку. Поскольку никакой другой подписки нет, остальная часть Observable.Create никогда не происходит, так как наблюдаемые могут выполнять какие-либо действия только при наличии хотя бы одной подписки. Вторая подписка не подписана на создание наблюдаемой, это прослушивание побочного эффекта.

Я бы порекомендовал вам попробовать изменить первый звонок по подписке с

    .Subscribe();

до

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

или что-то в этом роде. Таким образом, вы можете увидеть, что происходит не так.

...