IErrorHandler接口令我困惑

时间:2013-01-20 06:50:22

标签: wcf exception-handling soapfault ierrorhandler

我创建了一个实现IErrorHandler和IServiceBehavior的类。我将行为添加到我的ServiceHost并运行它。

我试图了解IErrorHandler的原因是因为我不得不在try catch语句中包装所有与回调通道接口的服务代码而感到沮丧,并且想知道是否有全局方法可以捕获例外。

从我在StackOverflow上看到的内容来看,我发现它确实是我想要的东西。

然而,在执行中,它让我很困惑。如果我有合同方法,可以执行以下操作......

    Dictionary<IChatCallback, string> userChannels = new Dictionary<IChatCallback, string>();

    public void SendMessage(string message)
    {
        IChatCallback callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();
        string senderName = userChannels[callback];

        SendMessageToAllUsers(message, senderName);
    }

    public void SendMessageToAllUsers(string message, string sender)
    {
        foreach (var userChannel in userChannels.Keys)
        {
            userChannel.ReceiveMessage(new ChatMessage(message, sender));
        }
    }

如果客户端在我的服务器上并且他从地球表面掉下来并且通道出现故障,那么在我的服务器意识到通道出现故障之前似乎需要一段时间。即使我订阅了ICommunicationObject的事件,在服务器意识到频道出现故障之前似乎还需要一段时间。例如,如果有人正在发送消息而某人正在断开连接,并且正在同时传播消息。

现在,我有另一种方法,基本上定期ping客户端,以确定它们是否仍然存在,所以我可以从userChannel字典中删除它们。

IErrorHandler究竟应该如何帮助我?它似乎并没有完全帮助我的服务崩溃,即使它捕获错误。因为我的服务无法以超快的速度ping我的客户端,所以有时会在上一条引发异常的消息之后立即发出消息(我正在测试此消息)。它似乎处理了第一个,但第二个抛出了另一个未被捕获的异常,我的服务崩溃了,因为服务器试图与故障通道进行通信。现在,我的服务部门会清理那些故障通道,但它会定期清理。

我希望通过实现IErrorHandler,我可以避免将所有方法都包装在try {} catch {}块中......但似乎我仍然需要检查我是否正在与故障进行通信信道?

或许我只是不正确地使用IErrorHandler并认为它应该做的事情不应该做。我应该让我的服务实现它,并将自己作为IServiceBehavior注入Servicehost吗?然后在我的HandleError()方法中从我的客户列表中删除该频道?这看起来有点混乱,因为我将WCF管道内容放在我的服务类中,但这是我能想到的唯一方法让异常代码本身从回调列表中删除该通道。

我正在尝试进行大量阅读,因为我是新手,但看起来WCF中的错误处理世界令人生畏。

即使我尝试删除通道,因此没有通过订阅Faulted事件调用服务,它也不能足够快地工作,并且仍然会引发异常,即使使用IErrorHandler,服务器似乎也无法恢复。

例如,当用户第一次连接时,我订阅了该事件。

        IChatCallback callback = OperationContext.Current.GetCallbackChannel<IChatCallback>();
        ICommunicationObject callbackComm = (ICommunicationObject) callback;
        callbackComm.Faulted += (sender, e) =>
            {
                lock (lockObject)
                {
                    string name = userChannels[callback];
                    userChannels.Remove(callback);
                    NotifyOfUserDisconnect(name);
                }
            };

我是否只需要进入我的所有方法并检查通道是否已关闭或出现故障,并将所有内容包装在try / catch块中以删除引用并通知客户端?

0 个答案:

没有答案