WPF で未処理の例外を使用して、「興味深い」動作が発生しているようです。
簡単に言えば、ディスパッチャ スレッドで短期間に同じ例外が 2 回スローされると、ディスパッチャの未処理の例外ハンドラがバイパスされ、アプリケーションがダウンします。
ステップを再現
- 新しい WPF アプリケーションを作成する
- DispatcherUnhandledException ハンドラーを作成し、e.Handled を true に設定して、例外を表示するメッセージ ボックスを開きます。
- AppDomain.CurrentDomain.UnhandledException ハンドラーを作成し、ここからもメッセージ ボックスを表示します (ここで例外を処理できないことに注意してください。ここで例外を処理すると、アプリが停止しようとしていることを意味します)。
ここでボタンを追加し、クリック ハンドラーに以下を追加します。
SynchronizationContext.Current.Post(s => { throw new Exception(); }, null); SynchronizationContext.Current.Post(s => { throw new Exception(); }, null);
DispatcherUnhandledException ハンドラーが 2 回発生し、両方の例外が処理され、すべてが正常であることがわかります。
ただし、上記のコードを次のように変更します。
var ex = new Exception();
SynchronizationContext.Current.Post(s => { throw ex; }, null);
SynchronizationContext.Current.Post(s => { throw ex; }, null);
そして、AppDomain.CurrentDomain.UnhandledException ハンドラーが発生し、アプリケーションが典型的なウィンドウの「デバッグしますか?」ダイアログでクラッシュすることがわかります。
追加情報
この例は、問題を単純化するために考案されたものに見えるかもしれません。ただし、このシナリオは、ストリームに 2 つの RX サブスクライバーがあり、エラーが発生した場合に発生する可能性があります。この場合、両方のサブスクライバーが同じ例外を発生させ、上記と同じ動作を引き起こします。たとえば、ボタン クリック ハンドラーの次の RX コードでも問題が再現されます (これも不自然ですが、同等の状況になる可能性があります)。
var o = Observable.Start(() => { throw new Exception(); }).Publish();
o.ObserveOnDispatcher().Subscribe(_ => { });
o.ObserveOnDispatcher().Subscribe(_ => { });
o.Connect();