这有点棘手,但我找到的唯一方法。我希望这对其他人有帮助。这个想法是不要让异常被抛出,而是创建一个 UnhendledExceptionEventArg 并将其传递给您的 UI 层。这是一些示例代码:
public class BuggySubscriber : IDisposable
{
public BuggySubscriber(string dataSourceName)
{
SyncContext = SynchronizationContext.Current;
Subscriber = new MockSubscriber(dataSourceName);
Subscriber.Refreshed += OnDataChanged;
}
public SynchronizationContext SyncContext { get; set; }
public event EventHandler<UnhandledExceptionEventArgs> ExceptionOccurred;
// Bouncing Exception Step 3
private void OnExceptionOccured(Exception ex)
{
var callback = new SendOrPostCallback(delegate
{
var handler = ExceptionOccurred;
if (!ReferenceEquals(handler, null))
handler(this, new UnhandledExceptionEventArgs(ex, true));
});
SyncContext.Post(callback, null);
}
void OnDataChanged(object sender, ServiceModel.DataChanged.DataChangedEventArgs e)
{
// Bouncing Exception Step 1 & 2
OnExceptionOccured(new NotImplementedException());
}
所以这是“子”代码。在 WPF 应用程序中,我在应用程序启动时添加以下内容:
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
BuggySubscriber.ExceptionOccurred += Sub_ExceptionOccurred;
...
}
// Bouncing Exception Step 5
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
if (!ReferenceEquals(exception, null))
ShowErrorMessage(exception);
}
// Bouncing Exception Step 4
void Sub_ExceptionOccurred(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
if (!ReferenceEquals(exception, null))
throw exception;
}
所以现在让我们尝试跟踪弹跳异常。
- 在现实生活中,订阅者被通知并且发生异常并被捕获。(在我的示例中,我没有显示。)
- 然后调用 OnExceptionOccurred(Exception ex)。
- 然后使用 ExceptionOccurred 事件创建 SendOrPostCallback,然后对当前 SynchronizationContext 执行 Post。
- 为 ExceptionOccurred 注册的 WPF 应用程序(现在,如果您愿意,您可以在此处处理异常消息...我选择对异常使用两条路径而不是三个。)它强制转换并抛出异常。
- 现在 CurrentDomain_UnhandledException 处理它并向用户显示一条错误消息(就在它退出之前)。
我确信这有很多变体,但这确实显示了一些我在一个地方找不到的更棘手的代码。
注意:这并不能解决任何频道问题。如果您有异常,您可以从中恢复,您仍然需要重新建立通道,因为它将出现故障或关闭。