Exception handling 将异常转换为IObservable异常

Exception handling 将异常转换为IObservable异常,exception-handling,system.reactive,Exception Handling,System.reactive,我有以下代码: var s = Observable .StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri)) .SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync())) .Select(ParseToMD); 解析的Tomd非常简单: private static IDocumentMet

我有以下代码:

var s = Observable
    .StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
    .SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
    .Select(ParseToMD);
解析的Tomd非常简单:

private static IDocumentMetadata ParseToMD(string marc21XML)
{
    return MARC21Parser.ParseForMetadata(marc21XML);
}
不幸的是,ParseForMetadata抛出异常是合法的。我非常希望能够使用正常的接收技术来处理异常。例如:

var goodOrEmpty = s.Catch(Observable.Empty<Tuple<PaperStub, PaperFullInfo>>());
var goodOrEmpty=s.Catch(Observable.Empty());

我怎样才能正确地保护Select调用,使异常在出错时正确地转换为IObservable?我还需要为其他人做这件事(StartAsync)。

我遵循的模式与处理异常的标准方式略有不同。select抛出异常并不一定意味着订阅不好。下一个事件可能会很好

请注意,在RX中,触发OneError意味着订阅必须终止

我所做的是将我的选择封装在一元异常类型中,以执行以下操作

Exceptional<IDocumentMetadata> s = Observable
    .StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
    .SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
    .SelectExceptional(ParseToMD);
或者你可以像这样投射它

    var Exceptional<ProcessedDocumentType> = 
        s.Select(document => ProcessDocument(document))
要获取该值,可以访问该属性

T Value
但是,如果您只是对良好的值进行操作,而不需要异常,则应使用Select和SelectMany

我的实现基于


从您的评论中,我想知道您是否看到了使用
StartAsync
而不是
fromsync
的效果。这些方法在一个重要细节上有所不同;前者在评估后立即运行一次,即无论有多少订阅者,它都只运行一次。如果没有订户,并且它抛出了一个异常,那么您将有一个未观察到的异常。与订阅时每个订阅者调用的async
fromsync
相反。

您应该得到一个按原样使用该代码的OnError。你不是吗?当我有“.Catch”时,我会得到一个未处理的异常。你是对的,这段代码中还有更多的东西。我试着在一个最小的测试中将其隔离,结果Catch按预期工作。所以我还遗漏了其他一些事情。当我做出来的时候会更多。谢谢啊。事实证明,这与调试器有关。当我在调试器下运行时,我有时会捕获这个异常(但不总是),它会声明它“未处理”。然而,当我真正让事情运行时,代码继续运行,就好像.Catch工作正常一样。因此,调试器可能不了解Rx是如何处理异常的?当我启用“中断抛出的异常”时,我经常被欺骗,认为异常未被处理。这里可能是这样吗?哦,有趣的想法。是的,我认为这可能是.NET4.0不同于.NET4.5.x的一个棘手的例子。我没有在.NET4.0上测试过它-但是.NET4.5上的RX2.2只是在输出中显示了第一次机会的异常(无论这看起来多么错误,异常不应该消失!)啊!谢谢我不喜欢这个。我现在注意到(脸红),在我的笔记中,我有一些关于理解这两者之间的区别的东西,但还没有做到。我一直在使用它们,但并没有真正考虑它们——所以我敢打赌,我的代码中还有其他尚未发现的bug。谢谢啊,非常好,谢谢。我之所以这样做是因为我的s.Catch()表达式位于SelectMany中:它只是意味着这个特定的搜索字符串有问题,而不是用户输入的下一个搜索字符串有问题。然而,我的方法是“原始”的,而你的方法很好封装,因此易于重用!
bool HasException
Exception Exception 
T Value