2

我正在开发一个使用 WCF 在服务器和客户端之间进行通信的应用程序服务器具有不断变化的服务数量,以及一个主服务,客户端可以查询有关其他服务的信息,然后使用来自主服务的信息订阅他们想要的服务.

主服务向订阅的客户端发送通知,当子服务更改(添加、删除等)时,子服务也每隔几秒发送一次通知。

这听起来像是使用 WCF 回调通道的绝佳机会,但是,它们需要您使用会话。此外,在向客户端发送通知时,当任何客户端不光彩地断开连接时,服务会挂起,试图通知它。即使超时,一段时间后,在此期间没有其他客户端得到通知,这是不可接受的,因为客户端实际上是用于监控子服务后面的应用程序的 GUI。也不能为此使用 MSMQ,因为服务需要立即知道发送操作何时不成功。

我想出的解决方案是使用 http 绑定(发送不成功时立即知道)并在客户端上创建显式回调服务,但这需要我编写很多难看的基础设施代码。

所以,我的问题是:有没有更好的方法来使用 WCF 做到这一点。最好看的选择是回调合同,因为这使我无需手动管理回调服务,只要它在尝试发送到下一个客户端之前不能等待来自一个客户端的确认。

4

1 回答 1

3

我有一个类似的环境(没有动态服务),并且在客户端通道出现故障时遇到了非常类似的问题。我想出的第一个解决方案是将回调包装在 try/catch 语句中,并在出现问题时删除有问题的客户端,但这有问题并且看起来根本不会扩展。

我最终采用的解决方案是使用委托事件处理程序并使用 BeginInvoke 调用它。如果您还没有查看过CodeProject:WCF/WPF 聊天应用程序 (Chatters)解决方案,我建议您查看一下。

当用户登录时,会创建一个事件处理程序并将其添加到主事件中:

public bool Login() 
{
    ...
    _myEventHandler = new ChatEventHandler(MyEventHandler);
    ChatEvent += _myEventHandler;
    ...
}

每当需要广播消息时,都会异步调用事件处理程序:

private void BroadcastMessage(ChatEventArgs e)
{
    ChatEventHandler temp = ChatEvent;
    if (temp != null)
    {
        foreach (ChatEventHandler handler in temp.GetInvocationList())
        {
            handler.BeginInvoke(this, e, new AsyncCallback(EndAsync), null);
        }
    }
}

当返回返回时,结果会被处理,如果发生了不好的事情,该通道的事件处理程序将被删除:

private void EndAsync(IAsyncResult ar)
{
    ChatEventHandler d = null;
    try
    {
        //get the standard System.Runtime.Remoting.Messaging.AsyncResult,and then
        //cast it to the correct delegate type, and do an end invoke
        System.Runtime.Remoting.Messaging.AsyncResult asres = (System.Runtime.Remoting.Messaging.AsyncResult)ar;
        d = ((ChatEventHandler)asres.AsyncDelegate);
        d.EndInvoke(ar);
    }
    catch(Exception ex)
    {
        ChatEvent -= d;
    }
}

上面的代码是从Sacha Barber发布的 WCF/WPF 聊天应用程序中修改的(稍微)。

于 2008-12-04T15:18:38.373 回答