Continue using subscription after exclusion

I tried the Reactive-Extensions Type-Search pattern, which takes a string from a text field (if it matters for a WPF application) and performs a potentially lengthy server-side search (modeled in my case using Thread.Sleep) and displays the result in the list.

Key features of this particular “module” will be:

  • asynchronous search; The user interface is not frozen in the search
  • strangled; quick writing will not result in a search on each side of the server on every page.
  • excellent search; after searching for "asd" and displaying the results (s) of fast input (backspace), d (that is, deleting the last character and redialing it) will not repeat the server-side search
  • drop mediation results; if I type “asd” and wait for a while (to start the launch on the server side), and then, BEFORE OUTPUT for asd, the end of the search string is displayed, these intermediate / specific results are discarded

the problem is that after one exception to the heavy method (the one that performs the “server search”), the subscription stops and cannot be used

So far, I have only discovered a workaround by re-subscribing to the IObservable object, but this seems to be wrong. I also tried .Retry (), but although I am using subscription again, my handler is OnErrorno longer called.

The code is as follows:

    private IObservable<object> _resultsFromTypeToSearch;

    private void SetupObserver()
    {
        var throttledUserInput =
            (from evt in Observable.FromEventPattern<TextChangedEventArgs>(TxtSearch, "TextChanged")
             select ((TextBox)evt.Sender).Text)
                .Throttle(TimeSpan.FromSeconds(0.6)) // this ensures that only after 0.6 seconds the user input is taken into consideration
                .DistinctUntilChanged();             // this ensures only changed input is taken into consideration

        var getDataFunc = new Func<string, object>(GetExpensiveData);
        var searchAsync = Observable.FromAsyncPattern<string, object>(getDataFunc.BeginInvoke, getDataFunc.EndInvoke);

        var z = from text in throttledUserInput
                from word in searchAsync(text).TakeUntil(throttledUserInput)
                select word;  // TakeUntil will drop an ongoing search if a new search is requested in the meantime
        _resultsFromTypeToSearch = z.ObserveOn(TxtSearch); // this ensures that we'll get notified on the UI thread
        _resultsFromTypeToSearch.Subscribe(PresentResults, OnError);
    }

    private void OnError(Exception obj)
    {
        ClearUI();
        MessageBox.Show("Error");

        _resultsFromTypeToSearch.Subscribe(PresentResults, OnError); // THIS IS MY WORKAROUND WHICH FEELS BAD
    }

    private void ClearUI()
    {
        IsBusy = false;
        Results.Clear();
    }

    private void PresentResults(object result)
    {
        ClearUI();
        Results.Add(result.ToString());
    }

    private object GetExpensiveData(string searchString)
    {
        IsBusy = true;
        if (DateTime.Now.Millisecond % 3 == 0) throw new ServerException();
        Thread.Sleep(2000);
        return "Data for " + searchString;
    }

Best way to do this?

+1
source share
2

Rx. , , . (), : SetupObserver()

0

Catch .

, , , Aync:

var searchAsync = Observable
    .FromAsyncPattern<string, object>(getDataFunc.BeginInvoke, getDataFunc.EndInvoke)
    .Catch(e => Observable.Empty<object>()) // eat the error and return "no results" for this search.

. . , , .

+1

All Articles