为什么在以下Rx代码中未命中catch块

本文关键字:catch 代码 Rx 为什么 | 更新日期: 2023-09-27 18:24:02

只是对流为什么没有到达catch块感到困惑。我知道,每当发生异常时,都会调用OnError方法,但调用ToObservable时不应该发生异常吗?只有在处理第三个数字(0)时,才会发生异常。我完全被说服了。

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

为什么在以下Rx代码中未命中catch块

Linq是延迟求值的,这意味着在调用Subscribe()之前不会求值,这就是为什么您的catch块没有命中

在Selector中引发与OnError'ing不同。某些运算符(如Start)会将代码包装在try/catch中并封送至OnError,但大多数运算符不会。想象一下,如果每个LINQ Select都包含在一个try/catch中!这会很慢。您的OnNext订阅也是如此。

如果你想创建一个确实有这种行为的Select版本,这里有一种方法:

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