初探Remoting双向通信(四)
初探Remoting双向通信(四)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kkkkkxiaofei/article/details/9175429 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-cd6c485e8b.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-cd6c485e8b.css">
<div class="htmledit_views" id="content_views">
之前已经从基本原理上实现了Remoting的双向通信。准备将其移植到我的项目中,不过为了成功移植,我还是需要再把以前的版本稍作修改才能放心的去做。项目中当一台机子中有工作人员进行了预警信息标记时(在地图上会有一个标志),其他机子需要同步更新。这就是说任何一个客户端进行标记时需要通知服务器,然后让服务器去广播标记。这一个小动作就需要双向通信一次。按照项目需求,我再次修改版本,这次只需要改一个函数:
修改服务器订阅事件函数如下:
-
void marshal_obj_SubscribeAtServer(string msg)
-
{
-
//跨线程调用
-
textBox2.Invoke(new Action<string>(str => { textBox2.AppendText(str); }), msg);
-
//订阅函数不在主线程,需另起线程触发广播方法
-
Thread th = new Thread(new ThreadStart(() => {
-
marshal_obj.TriggerAtServer("服务器--" + this.ServerIP() + System.Environment.NewLine + "我是服务器,我发现一个客户端有标记行为,我要让你们全部都标记!" + System.Environment.NewLine);
-
}));
-
th.Start();
-
}
然后开启一个服务器3个客户端,让其中一个客户端发起标记事件,效果如下:
有了这个,我更加肯定的去修改自己的项目了。经过一整天的大改,我把项目调试通了,开了1个服务器,2个客户端,分别设置了断点,虽然其中事件订阅处有很多逻辑处理,并不像上面DEMO那样只发送一段文字,但是每一个断点都可以运行到,那就说明整体上是通了。删除断点后,很高兴的看一下新的效果时,却让我大失所望:
当一个客户端进行标记时,第二个客户端确实也收到了信息,但是第一个客户端界面已经卡死,很久才能恢复,甚至当机。这就让我想起了上面这个Demo运行的效果时的现象了。上面的三个客户端收到信息并不是同时的,而是依次的。况且,所谓的广播发送,其实利用的就是多播委托,并不像Socket那样是3个tcpclient来进行通信的。服务器端利用Marshal得到的对象和3个客户端激活得到的对象是同一个引用(SingleTon方式),所以客户端订阅的事件都是在服务器同一个对象上的委托列表里。当直接调用委托的时候,调用的是委托的Invoke方法,该方法会在执行的时候阻塞当前线程,直到委托列表执行完才会将控制权转回来。这样一来,委托的超时必然会引起界面的假死(当有更多逻辑处理在事件订阅函数里时更糟糕)。呢有什么办法呢,查找了资料,看了"张子阳"的委托与事件觉得很不错,仔细拜读了好几遍。原来委托执行的列表是可以获取的,而且可以认为的去遍历,这么一来就可以解决许多问题:比如有一个客户端发生了异常,为了不影响其他的客户端,可以遍历的时候try/catch掉;再比如遍历的时候为了不阻塞客户端线程,可以每次另起一个线程(这里就用到了BeginInvoke,它就相当于另起线程执行委托,只不过它用的是线程池)。好了,再次修改以下服务器的订阅函数,如下:
-
void marshal_obj_SubscribeAtServer(string msg)
-
{
-
//跨线程调用
-
textBox2.Invoke(new Action<string>(str => { textBox2.AppendText(str); }), msg);
-
//遍历委托列表
-
Delegate[] del_list = marshal_obj.GetServerEventList();
-
foreach (Delegate del in del_list)
-
{
-
MyDelegate d = (MyDelegate)del;
-
d.BeginInvoke(
-
"服务器--" + this.ServerIP() + System.Environment.NewLine + "我是服务器,我发现一个客户端有标记行为,我要让你们全部都标记!" + System.Environment.NewLine,
-
null,
-
null);
-
}
-
}
其中GetServerEventList()这个方法是在远程对象里新加的:
-
//获取委托列表
-
public Delegate[] GetServerEventList()
-
{
-
return this.SubscribeAtClient.GetInvocationList();
-
}
这次,我开了很多客户端,接收到信息几乎是同步的(至少肉眼分辨不出来),并且将项目也进行了改进,也有了重大突破。感谢网上许多乐于分享的大牛们,Remoting的学习暂时告一段落,还有其他事情要做,前方的路已然坎坷,而我却乐此不疲。。。。。
(注:上面的Demo在此处下载http://download.csdn.net/detail/kkkkkxiaofei/5650187)
初探Remoting双向通信(四)的更多相关文章
- 初探Remoting双向通信(三)
原 初探Remoting双向通信(三) 2013年06月25日 17:51:08 喜欢特别冷的冬天下着雪 阅读数 4741 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- 初探Remoting双向通信(二)
原 初探Remoting双向通信(二) 2013年06月25日 11:46:24 喜欢特别冷的冬天下着雪 阅读数 2977 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- 初探remoting双向通信(一)
原 初探remoting双向通信(一) 2013年06月24日 15:47:07 喜欢特别冷的冬天下着雪 阅读数 4389 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- C# 实现Remoting双向通信
本篇文章主要介绍了C# 实现Remoting双向通信,.Net Remoting 是由客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象来实现通信的 闲来无事想玩玩双向通 ...
- C# Remoting双向通信
闲来无事想玩玩双向通信,实现类似QQ的互发消息的功能.于是乎开始学习.Net Remoting. .Net Remoting 是由客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为 ...
- 【Nacos】本地集群部署
关于Nacos已经展开了四篇入门文章: 初探Nacos(一)-- 单机模式启动 初探Nacos(二)-- SpringCloud使用Nacos的服务注册与发现 初探Nacos(三)-- SpringB ...
- C#进阶系列——DDD领域驱动设计初探(四):WCF搭建
前言:前面三篇分享了下DDD里面的两个主要特性:聚合和仓储.领域层的搭建基本完成,当然还涉及到领域事件和领域服务的部分,后面再项目搭建的过程中慢慢引入,博主的思路是先将整个架构走通,然后一步一步来添加 ...
- 【原创】NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
概述 本文演示的是一个Android客户端程序,通过UDP协议与两个典型的NIO框架服务端,实现跨平台双向通信的完整Demo. 当前由于NIO框架的流行,使得开发大并发.高性能的互联网服务端成为可能. ...
- 初探JavaScript(四)——作用域链和声明提前
前言:最近恰逢毕业季,千千万万的学生党开始步入社会,告别象牙塔似的学校生活.往往在人生的各个拐点的时候,情感丰富,感触颇深,各种对过去的美好的总结,对未来的展望.与此同时,也让诸多的老“园”工看完这些 ...
随机推荐
- Windows平台下在Emacs中使用plantuml中文乱码问题(已解决)
Windows平台下在Emacs中使用plantuml中文乱码问题(已解决) */--> code {color: #FF0000} pre.src {background-color: #00 ...
- sass的语法及其用法
1.sass语法 1.1 css的编译模式 css --- 普通 sass / scss --- 高效 // ********* less --- 高效 1.2 sass介绍 来源: ruby语言 基 ...
- SSM+Maven使用PageHelper插件分页
官方网站: https://pagehelper.github.io/docs/howtouse/#2-%E9%85%8D%E7%BD%AE%E6%8B%A6%E6%88%AA%E5%99%A8%E6 ...
- elasticsearch painless脚本评分
painless是一种新支持的脚本语言,语言格式和java十分类似.可以参考以下文档: painless语言介绍 painless api painless 实例 脚本参数 score_mode计算f ...
- 【Java学习笔记】百度面试问题回顾(一)
今天回顾了部分百度面试时被问到的问题: 1.常见的包装类有哪些,他们与基本类型的区别,有哪些方法? Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很 ...
- python-列表list- 元组(tuple)- 集合(set)-字典(dict)-实例代码
python 经常用的数据类型还有列表list- 元组(tuple)- 集合(set)-字典(dict),以下是这四种类型用法的简单示例. 1.列表list [ ] 元素可变 , 有序 ...
- 【leetcode】935. Knight Dialer
题目如下: A chess knight can move as indicated in the chess diagram below: . This time, we p ...
- spring boot 依赖配置
虽然springboot号称是零配置 配置文件确实不需要,但是 依赖还是要有的 <parent> <groupId>org.springframework.boo ...
- HTTP 错误 500.21 - Internal Server Error处理程序“NickLeeCallbackHandler”在其模块列表中有一个错误模块“ManagedPipelineHandler”
HTTP 错误 500.21 - Internal Server Error处理程序“NickLeeCallbackHandler”在其模块列表中有一个错误模块“ManagedPipelineHand ...
- SQL Server 2014 各版本介绍
SQL Server 2014 各版本介绍 目前,SQL Server 2014 分为主要版本和专业版. 在选择版本的时候可以根据您具体的需要进行抉择,如果你需要一个免费的数据库管理系统,那么就选择 ...