1

我创建了一个实现 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 中的错误处理世界似乎令人生畏。

即使我尝试删除通道,因此它不会通过订阅故障事件在服务上调用,但它的工作速度不够快,并且仍然会引发服务器似乎无法从 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 块中以删除引用并通知客户?

4

0 回答 0