简体   繁体   中英

How can I stop IConnectableObservable.Wait() from swallowing unhandled exceptions?

I have a console application using Rx.NET.

I need to block until an IConnectableObservable has completed, for which I am using IConnectableObservable.Wait() .

When an unhandled exception is thrown, it is swallowed and the application hangs. I want the application to crash, and the stack track to be printed to the console.

I do not want to add an OnError handler to my IConnectableObserver because this loses the original stack trace.

I have tried using the .Wait() method on the unpublished observable, but this re-subscribes which causes undesirable behaviour.

I have tried using .GetAwaiter().GetResult() instead, but this has the same problem.

var connectable = myObservable.Publish();

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

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

How can I wait for an IConnectableObservable to complete while retaining typical unhandled exception behaviour?

There's some misdirection in the chain of events here. The error isn't being swallowed - far from it, it's being re-thrown.

The usual suspects are some weird concurrency and scheduling issues, but nobody suspects the Subscribe method.

When you call Subscribe with something other than your own IObserver<T> , you're creating an AnonymousObserver with these default actions.

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

which is effectively

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

The default error handler will throw the error on whatever context you're observing on. Yikes. Sometimes it might be the AppDomain timer, or on a pooled thread, and since it can't be handled, your application goes down.

So if we change the sample to provide in a dummy handler,

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

You can handle the error in the Wait like you'd expect to.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM