我们在WPF中遇到了一些有趣的未处理异常行为。
简而言之,在短时间内在调度程序线程上抛出相同的异常两次将绕过调度程序未处理异常处理程序并关闭应用程序。
复现步骤
- Create a new WPF Application
- Create a DispatcherUnhandledException handler, set e.Handled to true and open a message box displaying the exception.
- Create a AppDomain.CurrentDomain.UnhandledException handler, show a message box from here too (note that you can't handle exceptions here so anything that makes it in here implies the app is about to go down).
Now add a button, and in the click handler add the following:
SynchronizationContext.Current.Post(s => { throw new Exception(); }, null); SynchronizationContext.Current.Post(s => { throw new Exception(); }, null);
然而,将上面的代码更改为以下内容:
var ex = new Exception();
SynchronizationContext.Current.Post(s => { throw ex; }, null);
SynchronizationContext.Current.Post(s => { throw ex; }, null);
你会发现AppDomain.CurrentDomain.UnhandledException处理程序被触发,应用程序将崩溃,并出现典型的Windows“是否要调试”对话框。
额外信息
这个例子似乎是人为制造的,只是为了简化问题。然而,如果你有两个RX订阅者订阅了一个错误流,那么就会发生这种情况。在这种情况下,两个订阅者都会引发相同的异常,导致与上述相同的行为。例如,按钮单击处理程序中的以下RX代码也会重现此问题(同样是人为制造的,但你可能会遇到等效的情况):
var o = Observable.Start(() => { throw new Exception(); }).Publish();
o.ObserveOnDispatcher().Subscribe(_ => { });
o.ObserveOnDispatcher().Subscribe(_ => { });
o.Connect();