0

以及如何将其呈现给用户?这篇文章:WCF Duplex:如何处理双工回调中抛出的异常与我的场景非常接近。这篇文章对于帮助我在通道出现故障时重新建立连接很有用。

我有一个发布应用程序 Pub 和一个订阅 WPF 应用程序 Sub。Pub 发送消息,Sub 已使用双工通道订阅回调。
Sub.ViewModel.ReactToChange(sender, e)尝试读取一些数据,但无法读取并引发异常。

DispatcherUnhandledException没有捕捉到它(我真的没想到。)
AppDomain.CurrentDomain.UnhandledException没有捕捉到它(这让我感到惊讶)
最终结果是我有一个仍在运行的应用程序,并且没有向用户显示异常消息所以他们可以纠正问题。有没有办法可以向用户显示该异常?

4

1 回答 1

0

这有点棘手,但我找到的唯一方法。我希望这对其他人有帮助。这个想法是不要让异常被抛出,而是创建一个 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;
        }

所以现在让我们尝试跟踪弹跳异常。

  1. 在现实生活中,订阅者被通知并且发生异常并被捕获。(在我的示例中,我没有显示。)
  2. 然后调用 OnExceptionOccurred(Exception ex)。
  3. 然后使用 ExceptionOccurred 事件创建 SendOrPostCallback,然后对当前 SynchronizationContext 执行 Post。
  4. 为 ExceptionOccurred 注册的 WPF 应用程序(现在,如果您愿意,您可以在此处处理异常消息...我选择对异常使用两条路径而不是三个。)它强制转换并抛出异常。
  5. 现在 CurrentDomain_UnhandledException 处理它并向用户显示一条错误消息(就在它退出之前)。

我确信这有很多变体,但这确实显示了一些我在一个地方找不到的更棘手的代码。
注意:这并不能解决任何频道问题。如果您有异常,您可以从中恢复,您仍然需要重新建立通道,因为它将出现故障或关闭。

于 2013-06-05T14:56:12.007 回答