Rx 2.1: Как правильно подписаться и наблюдать за Dispatcher

Прежде всего, я использую самый последний из Rx, то есть 2.1. Насколько я понимаю, когда Rx исполнилось 2 года, многое изменилось, поэтому я очень жду актуальный ответ. Заранее спасибо.

Я выполняю классическую задачу для Rx: наблюдаю за текстом TextBox (точнее, AutoCompleteBox из WPToolkit), чтобы предоставить пользователю список предложений. Предложения берутся из сети, и я хочу использовать эти обычные вкусности Rx, такие как Throttle, DistinctUntilChanged и т. д.

Я также использую недавно выпущенный HttpClient для Windows Phone 8, так как он предоставляет асинхронный API на основе задач, что приятно.

У меня возникла проблема с доступом между потоками при чтении значения Text в 'AutoCompleteBox`. Вот код:

var http = new HttpClient();
var searchFunc = Observable.FromAsync<HttpResponseMessage>(() => 
            http.GetAsync(FormatUrl(SEARCH_URL, "DE", new GeoCoordinate(51, 13), searchBox.Text /* <-- causes exception */, 10, "")));

var uithread = new SynchronizationContextScheduler(SynchronizationContext.Current);
var textChange = Observable.FromEventPattern<RoutedEventArgs>(searchBox, "TextChanged")                             
        .Throttle(TimeSpan.FromMilliseconds(800))
        .DistinctUntilChanged()     
        .SubscribeOn(uithread)           
        .SelectMany(searchFunc)                
        .Select(async (resp) => SearchResultsParser.ParseSearchResults(await resp.Content.ReadAsStreamAsync(), new GeoCoordinate(51, 13)))
        .Select(async (results) => searchBox.ItemsSource = await results)
        .ObserveOn(uithread)
        .Subscribe();

Исключение происходит, когда выполняется searchFunc. Я вижу из VS, что он выполняется в рабочем потоке, несмотря на то, что я использую SubscribeOn.

Вот пример с использованием SynchronizationContextScheduler, но я также пробовал использовать только SubscribeOnDispatcher с тем же результатом. Похоже, я упускаю что-то важное из этого ObserveOn или, может быть, из Observable.FromAsync. Не могли бы вы указать мне на мою ошибку?


person Haspemulator    schedule 28.02.2013    source источник
comment
Тот код, который вы вставили, откуда он выполняется? Внутри формы/элемента управления? (в принципе, это наверняка выполняется в потоке пользовательского интерфейса?)   -  person JerKimball    schedule 01.03.2013
comment
Да, это действительно выполняется в потоке пользовательского интерфейса. Это конструктор страницы.   -  person Haspemulator    schedule 01.03.2013


Ответы (1)


SubscribeOn почти никогда не бывает тем, что вам нужно — вы можете подумать, что это означает «Где работает мой метод Subscribe», но на самом деле это означает «Где проходит фактическая проводка к IDisposable (и удалению)» — ObserveOn является эквивалент для «Здесь я хочу, чтобы мой фактический код Subscribe выполнялся»

Ссылка: Observable.SubscribeOn и Observable.ObserveOn

person JerKimball    schedule 01.03.2013
comment
Неудачное название, т. - person Contango; 30.01.2015