2012-01-07 46 views
5

我越來越跨線程異常時使用RX油門

無效跨線程訪問。

當使用RX油門

這裏是我的代碼:

 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線程。不應該嗎?

回答

12

你SubscribeOnDispatcher的理解不正確。首先,讓我們區分兩個* On運算符:

  • SubscribeOn * - 在指定的調度程序上運行(聯合國)訂閱邏輯。很少使用,除非你玩Observable.Create等
  • ObserveOn * - 在指定的調度程序上運行觀察者消息(OnNext,OnError,OnCompleted)。運行傳遞給Subscribe的「事件處理程序」時,主要用於UI同步。

爲了讓您的示例工作,您還應該將ObserveOn運算符粘貼到查詢的下游。我們的建議是在最後的訂閱電話前執行此操作。在查詢中,可以通過諸如Throttle(其默認調度程序是線程池)等操作符引入併發。只有在你需要同步保證的地方,引入一個* On操作符。

保羅建議參數化Throttle調用也是一個很好的建議。如果您可以控制所有引入的併發,您可能需要這樣做。但是,在許多情況下,您將交付的IObservable序列在同步要求方面存在不良行爲,需要使用* On運算符。

4

就行更改爲:

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

這是更有效的,反正(雖然爲33ms是一個非常短的時間跨度油門,打了對計時器的分辨率)

+0

謝謝,這也適用。 – Vitalij 2012-01-10 22:48:24