我正在开发一个使用WCF在服务器和客户端之间进行通信的应用程序 服务器具有不断变化的服务数量,以及客户可以查询其他服务信息的一个主服务,然后使用主服务中的信息订阅他们想要的服务。
主服务在子服务更改(添加,删除等)时向订阅的客户端发送通知 此外,子服务每隔几秒钟发送一次通知。
这听起来像是使用WCF回调频道的绝佳机会,但是,它们要求您使用会话。此外,当向客户端发送通知时,当任何一个客户断断续续地断开连接时,服务会挂起,尝试通知它。即使它超时,经过一段时间,在此期间没有其他客户端得到通知,这是不可接受的,因为客户端实际上是用于在子服务后面单调应用程序的GUI。 同时使用MSMQ也不是一个选项,因为当发送操作没有成功时,服务需要立即知道。
我提出的解决方案是使用http绑定(在发送失败时立即知道)并在客户端上创建显式回调服务,但这需要我编写许多丑陋的基础架构代码。
所以,我的问题是:有没有更好的方法来使用WCF。最好看的选项是Callback Contracts,因为这样我就不需要手动管理回调服务,只要它在尝试发送到下一个客户端之前不能等待来自一个客户端的ack。
答案 0 :(得分:3)
我有一个类似的环境(没有动态服务),并且在客户端通道出现故障时也有类似的问题。我想出的第一个解决方案是将回调包装在try / catch语句中,如果出现问题就删除有问题的客户端,但是这有问题,看起来根本不会扩展。
我最终使用的解决方案是使用委托事件处理程序并使用BeginInvoke调用它。如果您还没有查看CodeProject: WCF/WPF Chat Application (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聊天应用程序中进行了修改。