Как я могу остановить IConnectableObservable.Wait () от проглатывания необработанных исключений? - PullRequest
2 голосов
/ 19 апреля 2020

У меня есть консольное приложение, использующее Rx. NET.

Мне нужно заблокировать до завершения IConnectableObservable, для которого я использую IConnectableObservable.Wait().

Когда необработанное исключение брошен, проглочен и приложение зависает. Я хочу, чтобы приложение обработало sh, а дорожка стека была распечатана на консоли.

Я не хочу добавлять обработчик OnError к моему IConnectableObserver, потому что при этом теряется исходная трассировка стека .

Я пытался использовать метод .Wait() на неопубликованной наблюдаемой, но эта повторная подписка вызывает нежелательное поведение.

Я пытался использовать .GetAwaiter().GetResult() вместо этого, но это имеет та же проблема.

var connectable = myObservable.Publish();

connectable.Subscribe(myObserver1);
connectable.Subscribe(myObserver2);

connectable.Connect();
connectcable.Wait();

Как я могу ждать завершения IConnectableObservable при сохранении типичного поведения необработанного исключения?

1 Ответ

1 голос
/ 19 апреля 2020

Здесь есть какое-то неверное направление в цепочке событий. Ошибка не проглатывается - отнюдь, она перебрасывается.

Обычные подозрения - это странные проблемы параллелизма и планирования, но никто не подозревает, что метод Subscribe.

Когда вы звоните Subscribe с чем-то отличным от вашего IObserver<T>, вы создаете AnonymousObserver с этими действиями по умолчанию.

new AnonymousObserver<T>(Ignore, Throw, Nop)

, что эффективно

new AnonymousObserver<T>(_ => {}, exn => throw exn, () => {})

Обработчик ошибок по умолчанию выдаст ошибку в любом контексте, в котором вы наблюдаете. Хлоп. Иногда это может быть таймер AppDomain или в потоке пула, и, поскольку он не может быть обработан, ваше приложение закрывается.

Так что, если мы изменим образец для предоставления в фиктивном обработчике,

var myObservable = Observable.Interval(TimeSpan.FromMilliseconds(100)).Take(4).Concat(Observable.Throw(new Exception(), 1L));
var connectable = myObservable.Publish();

connectable.Subscribe(Console.WriteLine, exn => Console.WriteLine("Handled"));
connectable.Subscribe(Console.WriteLine, exn => Console.WriteLine("Handled"));

connectable.Connect();

try
{
    connectable.Wait();
}
catch (Exception)
{
    Console.WriteLine("An error, but I'm safe");
}

Вы можете обработать ошибку в Wait, как и следовало ожидать.

...