Rx.NET不会触发onError也不会触发onComplete

时间:2017-01-25 01:57:54

标签: c# events asynchronous rx.net

我正在研究Rx.NET,在下面的示例代码中,我尝试执行异步任务,观察日期时间选择器值更改事件。 onNext运行完美但onError和onComplete不运行。我做错了什么?

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

1 个答案:

答案 0 :(得分:0)

当您不使用Rx并简单地附加事件处理程序时,该事件无法告诉您它已完成。处理程序将假设总是会有更多事件,即使它只被调用一次(想想js land中的onLoaded事件)。将事件转换为可观察事件时,您将看到相同的行为; Rx库无法知道事件流是否已经结束。

您始终可以使用Take方法来限制订阅者收到的项目数量。希望这有助于回答为什么观察者永远不会结束

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

至于OnError永远不会被调用 - 如果你的订阅者抛出一个错误,那么这是你的订阅者的问题,而不是observable本身,让所有其他订阅者知道一个sub变成了流氓是没有意义的。< / p>

OnError通常用于指示在序列中获取值时出错。 e.g。

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

    return Disposable.Empty;
});