使用RX油门时发生跨线程异常 [英] Cross thread exception when using RX Throttle

查看:31
本文介绍了使用RX油门时发生跨线程异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在获取


无效的跨线程访问。


使用RX油门时



这是我的代码:

  yObs.SubscribeOnDispatcher()
.DistinctUntilChanged()
.Throttle(TimeSpan.FromMilliseconds(33))
.SkipWhile(y =>!_isDragging)
.subscribe(y =>
{
//尝试访问图像
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)。在运行传递给订阅的事件处理程序时,通常用于UI同步。



为了使示例工作,您还应该让ObserveOn运算符在查询中进一步向下游使用。我们的建议是在最终的订阅电话之前执行此操作。在查询中,并发可由诸如Throttle(其默认调度程序为线程池)之类的运算符引入。仅在需要同步保证时,才引入* On运算符。



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


I am getting

Invalid cross-thread access.

When using RX Throttle

Here is my code:

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

But if I omit throttle everything works.

As far as I understand Throttle uses thread pool so OnNext doesn't happen on UI thread. But SubscribeOnDispatcher should marshal it back to the UI thread. Shouldn't it?

解决方案

Your understanding of SubscribeOnDispatcher is incorrect. First of all, let's distinguish between two *On operators:

  • SubscribeOn* - Runs the (un)subscription logic on the specified scheduler. Rarely used, unless you play with Observable.Create etc.
  • ObserveOn* - Runs the observer messages (OnNext, OnError, OnCompleted) on the specified scheduler. Mostly used for UI synchronization when running the "event handlers" passed to Subscribe.

In order for your sample to work, you also should stick the ObserveOn operator use further downstream in the query. Our recommendation is to do so right in front of the final Subscribe call. Within the query, concurrency can be introduced by operators such as Throttle (whose default scheduler is the thread pool). Only at the point you need synchronization guarantees, introduce a *On operator.

Paul's suggestion to parameterize the Throttle call is a good one too. In cases where you can control all the concurrency introduced, you may want to do so. However, there are many cases where you are handed an IObservable sequence that is ill-behaved with regards to synchronization requirements, requiring the use of *On operators.

这篇关于使用RX油门时发生跨线程异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆