使用RX Throttle时出现跨线程异常



我得到

无效的跨线程访问。

使用RX Throttle 时

这是我的代码:

        yObs.SubscribeOnDispatcher()
            .DistinctUntilChanged()
            .Throttle(TimeSpan.FromMilliseconds(33))
            .SkipWhile(y => !_isDragging)
            .Subscribe(y =>
                           {
                               // Exception when trying to access image
                               image.RenderTransform = new CompositeTransform() { TranslateY = -y };
                               _vm.UpdateContentDrag(y / image.ActualHeight * 100);
                           });

但如果我省略油门,一切都会起作用。

据我所知,Throttle使用线程池,所以OnNext不会发生在UI线程上。但是SubscribeOnDispatcher应该将它封送回UI线程。不是吗?

您对SubscribeOnDispatcher的理解不正确。首先,让我们区分两个*On运算符:

  • SubscribeOn*-在指定的计划程序上运行(取消)订阅逻辑。很少使用,除非你玩Observable。Create等
  • ObserveOn*-在指定的计划程序上运行观察者消息(OnNext、OnError、OnCompleted)。主要用于运行传递给Subscribe的"事件处理程序"时的UI同步

为了使您的示例能够工作,您还应该在查询的下游继续使用ObserveOn运算符。我们的建议是在最后的订阅电话前立即这样做。在查询中,并发性可以由诸如Throttle(其默认调度程序是线程池)之类的运算符引入。只有在需要同步保证的时候,才引入*On运算符。

Paul关于参数化Throttle调用的建议也是一个很好的建议。如果您可以控制引入的所有并发,您可能希望这样做。但是,在许多情况下,您会收到一个IObservable序列,该序列在同步要求方面表现不佳,需要使用*On运算符。

只需将行更改为:

.Throttle(TimeSpan.FromMilliseconds(33), DispatcherScheduler.Instance)

无论如何,它都更高效(尽管33ms是一个非常短的时间跨度节流阀,与计时器分辨率相冲突)

相关内容

  • 没有找到相关文章

最新更新