抛出异常的双工通道回调类方法。异常在哪里?

时间:2013-06-04 20:00:33

标签: wpf wcf exception-handling duplex-channel

我怎样才能将它呈现给用户? 这篇文章:WCF Duplex: How to handle thrown exception in duplex Callback非常接近我的情景。这篇文章对于帮助我在频道出现故障时重新建立连接非常有用。

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

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

1 个答案:

答案 0 :(得分: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()); 
    }

所以这是“Sub”代码。在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执行发布。
  4. 为ExceptionOccurred注册的WPF应用程序(现在,如果您愿意,可以在此处理异常消息...我选择使用两个路径用于异常而不是三个。)它会抛出并抛出异常。
  5. 现在,CurrentDomain_UnhandledException处理它并向用户显示错误消息(在它退出之前)。
  6. 我确信这有很多变化,但这确实显示了一些我在一个地方找不到的棘手代码。
    注意:这不能解决任何渠道问题。如果您有异常,您可以从中恢复,仍然需要重新建立该频道,因为它将出现故障或关闭。