0

我正在研究 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");
        });
}
4

1 回答 1

0

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

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

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

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

OnError 通常用于指示获取序列中的值时出错。例如

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

    return Disposable.Empty;
});
于 2017-04-20T14:41:47.620 回答