观察者<T>。OnError 的假设似乎与 Stubs.Throw 不一致。



IObservable的重载之一。订阅是

public static IDisposable Subscribe<T>(this IObservable<T> source, Action<T> onNext)

在内部,它在IObservable上创建并注册了一个AnoymousObserver<T>。未指定的onError参数被设置为Stubs.Throw,这是一个简单的lambda,它会重新抛出传入的异常。

在内部,IObservable的观察者都包含在Observer类型的单个实例中。这是Observer<T>.OnError

中的代码
public void OnError(Exception error)
{
    foreach (var observer in _observers.Data)
        observer.OnError(error);
}

因为存根。Throw抛出异常,该观察者的OnError异常通过foreach循环和_observer中的其他观察者向上传递。Data永远不会调用它们的OnError。异常本身被吞噬在Rx中的某个地方。

在我看来,观察者OnError应该包装观察者。try-catch或stub中的OnError。Throw应该吞下异常而不是抛出异常。通过不传递onError参数,IObservable的用户。Subscribe希望仅对该订阅忽略错误。其他使用自己的onError回调函数注册的订阅者应该不受影响。

(我已经在Codeplex上提交了一个bug,但是跟踪器看起来被遗弃了,所以我想我也会问一下,看看我是否理解正确。)


更新:Asti的答案是正确的。在链接的bug报告的讨论中,davedev给出了IEnumerable的类比,以及默认抛出未处理的异常如何等同于默认迭代IEnumerable而不使用catch块。

如果可观察对象确定一个特定的异常不应该被认为是致命的,它不应该使用OnError进行通信。OnError不能保证被执行,因为调用它意味着可观察对象一开始就出现了严重的错误。相反,可观察对象可以定义为IObservable<T,>>

这实际上是预期的行为。

OnError不是一个用来指示在观察者的OnNext上抛出异常的方法,它是用来指示一个可观察序列的异常终止。默认的OnError实现会在通知从Observable单子中转移出去时抛出异常。

如果你阅读了Rx设计指南,你会对Rx合约和异常处理有更清晰的了解。至于管道中的错误处理,以及更多类似IEnumerable/IQueryable的行为,请查看SubscribeSafe

相关内容

  • 没有找到相关文章

最新更新