离上一篇完工似乎又好多天没有更新了,不是因为后续没有什么可写,而是发现后续的问题真的还有好多,一点一点的尝试解决真的是需要一些时间,并且也不想涂鸦般的到网上搜些毫无心得的代码往这里一贴草草敷衍。而是真的希望给自己的这个尝试留个结果,给对这个新技术感兴趣的朋友一点帮助或思路了。
好了,废话少说,回归正题。今天这个帖子严格讲还是延续Silverlight3学习笔记5(Silverlight,WCF双工通信) 和Silverlight3学习笔记4(Silverlight,WCF通信)的内容,不过前面这两篇应该侧重的是如何搭建一个基本的,且完全可用的项目架子。而今天这篇就应该是希望在这个架子上来探讨下如何解决在Silverlight与WCF通信的模式下遇到的一些问题。
这篇首先列出需要讨论的两个问题,
问题1:客户端的非代码退出,服务端如何处理?(下面简称:问题1)
问题2:客户端的刷新,服务端如何处理?(下面简称:问题2)
先说下问题的由来与重要性,以及如何解决
问题1:这个问题简单说应该是当客户端关闭该URL连接时,服务端该如何处理了,如果这个问题是对原Asp.net或是Jsp的web应用来说关闭链接后该客户端也就没有任何逻辑请求了,服务端当然也不会存在对WebClient请求的响应了,所以对于传统应用来说服务器端不会再有多余的处理(通常来说)。
但是对于目前的双工通信来说问题就不是这么简单了,如果已经写过类似尝试的代码的开发来说应该知道,服务器端如果需要向客户端推消息的话,必须要在服务端首先获得了Client端的Callback对象,通过该回调句柄来发起对Client的回写。
这个时候问题就来了,如果Client端没有通过应用提供的途径关闭了应用,而此时保存在服务端的客户回调句柄就不存在真正的接受方了。
对于该问题,其实从最简单的方式来考虑,处理也可以很简单,对于循环向保留在服务端的每个回调句柄发送消息时,都用异常扑捉块来捕获异常,一旦发现某个回调对象做回调时发生异常,则将该回调对象从服务端移除。
看起来这样处理很简单,但是该解决同样还有相当的不足。对于做客户端回调时,只有在执行到超时时才能引发超时异常,并且该回调是线程阻塞的,也就是如果超时异常没有到达前,服务端就完全等待了。也就是说管理回调的整个方法体如果没有完成的话,所有需要获得服务端回调的客户端都没有办法接收到回调的消息。
在这里我尝试的处理方式就是采用多线程的方式来对所有Client回调对象的管理。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
该类可以对回调进行管理调度。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
该类为完成回调的具体线程实现。
这部分代码可能还存在对线程管理上的不足,希望能抛砖引玉了。不管线程管理如何但是通过尝试该方法服务端对客户端的回调不会再有阻塞的问题了。并且也可以将已经非正常关闭的Client回调句柄管理起来,以这种思路应该可以在新的线程能对回调对象做更多的操作,完成需要的逻辑。
问题2:这个刷新问题比较好理解了,类似的情况在Asp.net的页面刷新也应该存在,不过其中的表现形式与该双工通信还不是十分一样了,当然这里的根本问题还在于对保留在服务端的回调句柄的处理,通常我们在双工通信时,服务端获得回调句柄,需要通过
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
{
IDuplexClient client = OperationContext.Current.GetCallbackChannel<IDuplexClient>();
clientHelp.RegisterClient(client, input);
clientHelp.NoticeOnlineUser();
}
的方式来获得,可以看到该获得的回调句柄是从,一次请求的OperationContext中获得,也就是说如果一次请求的OperationContext如果出现了差异,那从该上下文中获得的回调句柄也必然出现不一致。
说了这些的目的起始就是想说明,如果对于Silverlight客户端刷新后,对该方法体的调用,就会造成回调客户端的不一致。
对于处理该问题的解决方案来看,我自己感觉应该没有什么好的解决办法,不过如果从业务逻辑的角度来看,应该可以避免该问题的发生,解决的办法就是对于一个Client来说除非其退出或关闭,在服务端创建一次回调句柄就应该足够了。
突然想起一个问题,如果句柄获得后,且客户端也做了刷新,那保留在服务端的回调句柄回调会不会失效?
如果不失效,依然可以推到该客户机上,那上面的实现应该是OK的,如果失效,那刷新问题似乎依然没有很好解决了。
这个问题不好意思了,等我好好试试后,在这个帖子后补上!见谅!