为什么在下面的Rx代码中没有命中catch块?

时间:2012-02-11 12:33:52

标签: c# exception exception-handling system.reactive catch-block

只是混淆了为什么流量没有达到阻挡块。我确实理解,每当发生异常OnError时,都会调用ToObservable方法,但调用 static void Main() { try { var numbers = from number in new int[] { 1, 2, 0, 3 } select 10 / number; var observable = numbers.ToObservable(); observable.Subscribe(OnNext, OnError, OnComplete); Console.ReadKey(); } catch (Exception exc) { Console.WriteLine("Program terminated with the following message - {0}", exc.Message); } } private static void OnNext(int i) { Console.WriteLine("Output : " + i); } private static void OnError(Exception exc) { Console.WriteLine("In oops : {0}", exc.Message); } private static void OnComplete() { Console.WriteLine("In done"); } 时不应该发生异常?只有在处理第三个数字(0)时才会发生异常。我完全被困扰了。

{{1}}

2 个答案:

答案 0 :(得分:3)

Linq被懒惰地评估,这意味着在你调用Subscribe()之前不会评估任何内容,这就是你的catch块未被命中的原因

答案 1 :(得分:1)

投掷选择器与OnError'ing不同。某些运算符(如Start)会将您的代码包装在try / catch中并编组为OnError,但大多数操作符都不会。想象一下,如果每个LINQ Select都包含在try / catch中!它会很慢。您的OnNext订阅也是如此。

如果你想创建一个的选择版本有这种行为,这是一种方法:

public static IObservable<TRet> SafeSelect(this IObservable<T> This, Func<T,TRet> selector)
{
    return This.SelectMany(x => {
        try {
            return Observable.Return(selector(x));
        } catch (Exception ex) {
            return Observable.Throw<TRet>(ex);
        }
    });
}