Почему блок catch не срабатывает в следующем коде Rx? - PullRequest
0 голосов
/ 11 февраля 2012

Просто запутался, почему поток не достигает блока захвата. Я понимаю, что при возникновении исключения будет вызываться метод 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");
        }

Ответы [ 2 ]

3 голосов
/ 11 февраля 2012

Linq оценивается лениво, это означает, что ничего не оценивается, пока вы не вызовете Subscribe(), поэтому ваш блок catch не срабатывает

1 голос
/ 11 февраля 2012

Добавление в селектор не то же самое, что OnError'ing. Некоторые операторы, такие как Start, упаковывают ваш код в try / catch и маршалируют в OnError, но большинство этого не делают. Представьте, что каждый LINQ Select был обернут в попытку / поймать! Это было бы довольно медленно. То же самое касается вашей подписки 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);
        }
    });
}
...