Observable.Retry () не работает должным образом с горячими наблюдаемыми - PullRequest
0 голосов
/ 09 мая 2018

У меня есть следующая наблюдаемая последовательность

int num = 0;            

var o = Observable.Create<int>(observer => Task.Run(() =>
{
    var rnd = new Random((int)DateTime.Now.Ticks);
    Console.WriteLine($"Starting subscription loop # {++num}");
    for (int i=0;i<100;i++)
    {
        Thread.Sleep(200);

        if (i == 3)
        {
            observer.OnError(new ApplicationException("test exception"));
            break;
        }

        observer.OnNext(rnd.Next(0, 50));
    }
})).Publish().RefCount();

и следующий обработчик уведомлений

o
    .Retry()
    .Subscribe(Console.WriteLine, ex => Console.WriteLine($"Exception occurred: {ex.Message}"), () => Console.WriteLine("Completed"));

Вот мой вывод

Starting subscription loop # 1
47
27
12
Starting subscription loop # 2
Starting subscription loop # 3
Starting subscription loop # 4
Starting subscription loop # 5
Starting subscription loop # 6
Starting subscription loop # 7
Starting subscription loop # 8
Starting subscription loop # 9
...

Я прочитал следующее в IntroToRx Ли Кэмпбелла книга

Если вы ожидаете, что ваша последовательность столкнется с предсказуемыми проблемами, Вы можете просто повторить попытку. Один из таких примеров, когда вы хотите повторная попытка выполняется при выполнении операций ввода-вывода (таких как веб-запрос или доступ к диску). I / O славится случайными сбоями. Метод расширения Retry предлагает возможность повторить попытку отказа указанное количество раз или пока это не удастся.

Поведение, которое я заметил в моем образце, не соответствует поведению, которое записал Кэмпбелл, и не соответствует его образцам. Чего мне не хватает?

Хорошо работает, если я не Publish().RefCount().

1 Ответ

0 голосов
/ 09 мая 2018

Когда наблюдаемая ошибка выходит из строя, она мертва и закончена. Больше никаких уведомлений не должно вытекать. В вашем случае, o выдает ошибку, и из-за .Publish().Refcount(), Retry пытается повторно подписаться на ту же самую наблюдаемую (которая является мертвой и законченной). Вот что делает Publish: вместо создания новых наблюдаемых он подписывает несколько клиентов на одни и те же наблюдаемые.

Если вы удалите .Publish().Refcount(), вы увидите, что она пытается повторно подписаться на новую заметку.

...