0

I'm studying Rx.NET and in the sample code below I'm trying to perform an async task observing date time picker value changed event. The onNext runs perfectly but onError and onComplete do not. What am I doing wrong?

private void frmReporting_Load(object sender, EventArgs e){
    dtPickerValueChanged = Observable.FromEventPattern(
        ev => dtPickerFrom.ValueChanged += ev, 
        ev => dtPickerFrom.ValueChanged -= ev);

    dtPickerValueChanged = dtPickerValueChanged.Merge(Observable.FromEventPattern(
        ev => dtPickerTo.ValueChanged += ev, 
        ev => dtPickerTo.ValueChanged -= ev));

    dtPickerValueChanged    
        .Where(x => dtPickerFrom.Value <= dtPickerTo.Value)
        .Finally(() => { tsslStatus.Text = "Finally";  })    
        .ObserveOn(SynchronizationContext.Current)
        .Subscribe(
            onNext: async x => {
                var result = await Test(dtPickerFrom.Value, dtPickerTo.Value);
                MessageBox.Show(result);  
            }, 
            onError: exception => { MessageBox.Show(exception.Message); }, 
            onCompleted: () => { MessageBox.Show("Finished loading data"); });
}

public Task<string> Test(DateTime start, DateTime end){
    return Task.Run(
        async () =>
        {
            await Task.Delay(3000);
            return start.ToString("dd/MM/yyyy - HH:mm:ss") + " | " + end.ToString("dd/MM/yyyy - HH:mm:ss");
        });
}
Jacob
  • 77,566
  • 24
  • 149
  • 228
  • Why are you expecting `onError` or `onCompleted` to fire? Nothing is ending your event stream or throwing errors. – Jacob Jan 25 '17 at 02:19
  • If I add a throw new Exception("whatever") inside the onNext it won't catch it up on onErrror. Regarding onCompleted how can I end the observable wheteher it's not disposable? I've seen many tutorials and code example but I've never found a good explanation about when each action is called. – Alexandre Coelho Jan 25 '17 at 02:30

1 Answers1

0

When you don't use Rx and simply attach an event handler, that event has no way of telling you that it's complete. The handler will assume that there will always be more events even if it's only invoked once (think onLoaded event in js land). When converting the event to an observable you'll see the same behaviour; the Rx library has no way of knowing whether the event stream has ended.

You can always make use of the Take methods to limit the amount of items your subscriber receives. Hope this helps answer why the observables never end

MouseMove.TakeUntil(MouseUp).Subscribe(...);
DocLoad.Take(1).Subscribe(...);

As for the OnError never being called - if your subscriber throws an error then this is a problem with your subscriber, not the observable itself and it would make no sense to let all the other subscribers know that one sub went rogue.

OnError is usually used for indicating that there was an error obtaining a value in the squence. e.g.

Observable.Create(sub => {
    try {
        var res = SomethingThatCanThrow();
        sub.OnNext(res);
        sub.OnCompleted();
    } catch (Exception ex) {
        sub.OnError(ex);
    }

    return Disposable.Empty;
});
Aaron
  • 188
  • 1
  • 7