Remoting的事件机制(带具体例子)

使用.NET Remoting从服务器主动发出事件通知客户端远程广播 使用.NET Remoting从服务器主动发出事件通知客户端(远程广播) 经常看见有人问:使用.NET Remoting如何从服务器主动发出事件通知客户端?的确,初接触.NET Remoting的人多半会有这样的疑问,因为大部分的文章和书籍在介绍.NET Remoting时都只介绍了通道,对象,激活和生存周期等等概念,在谈到如何进行远程通信的时候,都只告诉读者如何从客户端激活一个服务器对象然后传递参数调用其方法。所以很多读者都不太清楚如何从服务器向客户端广播信息,甚至有很多人认为跟WEB服务器不能主动发送信息到浏览器一样,.NET Remoting同样也不能这么做,只能采用"客户端发出请求->服务器回复响应"这种简单的通讯模式,以至于在需要服务器对客户端广播信息时设计出两端都放上Server和Client对象的复杂架构,既麻烦又容易出错。 其实.NET Remoting远程处理完全支持事件驱动的编程和使用同步和异步委托的回调函数。在.NET Remoting中你可以方便的采用事件注册远程回调函数,并方便的利用这种机制将服务器端信息广播到客户端。 立即下载
概念就不说了,具体参见msdn相关章节:
http://msdn.microsoft.com/library/CHS/cpguide/html/cpconEvents.asp

我们先来改造一下上次的程序,为上次的主线程方法添加事件,能不断的引发事件来汇报处理的进度:
public   class  MyEventArgs
{
    
private   int  _rate;
    
    
public   int  Rate
    {
        
get
        {
            
return  _rate;
        }
    }

    
public  MyEventArgs( int  rate)
    {
        
this ._rate = rate;
    }
}

public   class  MyObject
{
    
public   delegate   void  MyEventHandler( object  sender,MyEventArgs e);
    
public   event  MyEventHandler MyEvent;

    
public   void  ALongTimeMethod( int  time)
    {
        Console.WriteLine(
" 主线程方法开始 " );
        
for ( int  i = 0 ;i < 100 ;i ++ )
        {
            System.Threading.Thread.Sleep(time);
            OnMyEvent(
new  MyEventArgs(i));
        }
        Console.WriteLine(
" 主线程方法结束 " );
    }

    
protected   void  OnMyEvent(MyEventArgs e)
    {
        
if  (MyEvent != null )
        {
            MyEvent(
this ,e);
        }
    }
}

再来为事件添加处理程序:

class  MyClient
{
    [STAThread]
    
static   void  Main( string [] args)
    {
        DateTime dt
= DateTime.Now;
        MyObject obj
= new  MyObject();
        obj.MyEvent
+= new  MyObject.MyEventHandler(obj_MyEvent);
        obj.ALongTimeMethod(
50 );
        Console.WriteLine(
" 用了 " + ((TimeSpan)(DateTime.Now - dt)).TotalSeconds + " 秒 " );
        Console.ReadLine();
    }

    
public   static   void  obj_MyEvent( object  sender,MyEventArgs e)
    {
        Console.WriteLine(
" 主线程方法完成了 " + e.Rate + " % " );
    } 
}

运行程序可以看到:

这个是本地的,远程对象的事件也这么简单吗?其实没有想象的简单,因为对象是在远程的,服务端的事件客户端怎么捕捉?应该说远程对象的事件可以分成客户端触发-》服务器应答,服务端触发-》客户端应答和客户端触发-》客户端应答,第一种就很简单了,后面2种都需要有一个中间件。下面我们来要为程对象同样来添加一个进度机制,首先来建立我们的远程对象:

[Serializable]
    
public   class  MyEventArgs:EventArgs
    {
        
private   int  _rate;
        
private   string  _ip;

        
public   int  Rate
        {
            
get
            {
                
return  _rate;
            }
        }

        
public   string  IP
        {
            
get
            {
                
return  _ip;
            }
        }

        
public  MyEventArgs( int  rate, string  ip)
        {
            
this ._rate = rate;
            
this ._ip = ip;
        }
    }

    
public   class  MyObject:MarshalByRefObject
    {
        
public   delegate   void  MyEventHandler( object  sender,MyEventArgs e);
        
public   event  MyEventHandler MyEvent;

        
public   int  ALongTimeMethod( int  a, int  b, int  time, string  ip)
        {
            Console.WriteLine(
" 异步方法开始 " );
            
for ( int  i = 0 ;i < 10 ;i ++ )
            {
                System.Threading.Thread.Sleep(time);
                OnMyEvent(
new  MyEventArgs(i,ip));
            }
            Console.WriteLine(
" 异步方法结束 " );
            
return  a + b;
        }

        
protected   void  OnMyEvent(MyEventArgs e)
        {
            
if  (MyEvent != null )
            {
                MyEvent(
this ,e);
            }
        }
    }

为了调试方便,服务器端和客户端这次都用程序实现,下面是服务器端:
using  System;
using  System.Collections;
using  System.Runtime.Remoting;
using  System.Runtime.Remoting.Channels;
using  System.Runtime.Remoting.Channels.Tcp;
using  System.Runtime.Serialization.Formatters;

namespace  RemoteServer
{
    
class  MyServer
    {
        [STAThread]
        
static   void  Main( string [] args)
        {
            RemotingConfiguration.RegisterWellKnownServiceType(
typeof (RemoteObject.MyObject), " RemoteObject.MyObject " ,WellKnownObjectMode.Singleton);
            BinaryServerFormatterSinkProvider serverProvider 
=   new  BinaryServerFormatterSinkProvider(); 
            BinaryClientFormatterSinkProvider clientProvider 
=   new  BinaryClientFormatterSinkProvider(); 
            serverProvider.TypeFilterLevel 
=  TypeFilterLevel.Full; 
            IDictionary props 
=   new  Hashtable(); 
            props[
" port " ] = 9999 ; 
            TcpChannel channel 
=   new  TcpChannel(props,clientProvider,serverProvider); 
            ChannelServices.RegisterChannel(channel); 
            Console.ReadLine();
        }
    }
}

客户端为了简单一点,我去除了前面做测试的本地事件:
using  System;
using  System.Net;
using  System.Collections;
using  System.Text;
using  System.Runtime.Remoting;
using  System.Runtime.Remoting.Channels;
using  System.Runtime.Remoting.Channels.Tcp;
using  System.Runtime.Serialization.Formatters;

class  MyClient
{
    
private   delegate   int  MyDelegate( int  a, int  b, int  time, string  ip);
    
private   static  MyDelegate md;

    [STAThread]
    
static   void  Main( string [] args)
    {
        DateTime dt
= DateTime.Now;
        RemotingConfiguration.RegisterWellKnownClientType(
typeof (RemoteObject.MyObject),  " tcp://localhost:9999/RemoteObject.MyObject " );
        BinaryServerFormatterSinkProvider serverProvider 
=   new  BinaryServerFormatterSinkProvider(); 
        BinaryClientFormatterSinkProvider clientProvider 
=   new  BinaryClientFormatterSinkProvider(); 
        serverProvider.TypeFilterLevel 
=  TypeFilterLevel.Full; 
        IDictionary props
= new  Hashtable(); 
        props[
" port " ] = 0 ; 
        TcpChannel channel 
=   new  TcpChannel(props,clientProvider,serverProvider); 
        ChannelServices.RegisterChannel(channel); 
        RemoteObject.MyObject app
= new  RemoteObject.MyObject();
        app.MyEvent
+= new  RemoteObject.MyObject.MyEventHandler(MyEvent);
        md
= new  MyDelegate(app.ALongTimeMethod);
        AsyncCallback ac
= new  AsyncCallback(MyClient.CallBack);
        IPHostEntry ipHE
= Dns.GetHostByName(Dns.GetHostName());
        IAsyncResult Iar
= md.BeginInvoke( 1 , 2 , 300 ,ipHE.AddressList[ 0 ].ToString(),ac, null );
        Method();
        Console.WriteLine(
" 用了 " + ((TimeSpan)(DateTime.Now - dt)).TotalSeconds + " 秒 " );
        ChannelServices.UnregisterChannel(channel);
        Console.ReadLine();
    }

    
public   static   void  CallBack(IAsyncResult Iar)
    {
        
if (Iar.IsCompleted)
        {
            Console.WriteLine(
" 结果是 " + md.EndInvoke(Iar));
        }
    }

    
public   static   void  MyEvent( object  sender,RemoteObject.MyEventArgs e)
    {
        Console.WriteLine(
" 来自 " + e.IP + " 的异步方法完成了 " + e.Rate * 10 + " % " );
    } 

    
public   static   void  Method()
    {
        Console.WriteLine(
" 主线程方法开始 " );
        System.Threading.Thread.Sleep(
5000 );
        Console.WriteLine(
" 主线程方法结束 " );
    }
}

代码看上去不错,可是debug启动后报错:
 
这就是我前面提到的问题,远程不可能有本地的程序集,也无法触发本地事件。解决办法就是加一个事件中间件,继承MarshalByRefObject:
public   class  EventClass:MarshalByRefObject
    {
        
public   void  MyEvent( object  sender,MyEventArgs e)
        {
            Console.WriteLine(
" 来自 " + e.IP + " 的异步方法完成了 " + e.Rate * 10 + " % " );
        } 
    }

然后来修改一下客户端:
把app.MyEvent+=new RemoteObject.MyObject.MyEventHandler(MyEvent);修改为
RemoteObject.EventClass ec = new  RemoteObject.EventClass();
        app.MyEvent
+= new  RemoteObject.MyObject.MyEventHandler(ec.MyEvent);
删除客户端的MyEvent静态方法。

运行一下程序:


前后两个窗口本别是服务端和客户端的,貌似达到了我们的要求,其实不然,程序有2个漏洞:
1、客户端关闭以后打开新的程序就出错,因为以前的委托链丢失,服务端程序企图触发事件出错。
2、同时打开几个客户端,客户端收到的是所有的进度信息,而不仅仅是自己的,广播性质的消息。
Remoting事件 是.net Remoting事件的简单例子,学习为主. 立即下载

相关推荐

remoting事件(客户端发传真)

remoting技术

(原创)一步一步学Remoting之六:事件(1)

                      一步一步学Remoting之六:事件(1) 周末又过去了要上班了,一大早起来继续写。 概念就不说了,具体参见msdn相关章节: http://msdn.microsoft.com/library/CHS/cpguide/html/cpconEvents.asp 我们先来改造一下上次的程序,为上次的主线程方法添加事件,能不断的引发事件来汇报处理的进度: ...

weixin_34148340的博客 180

GEOSHIELD:分布式CPS的拜占庭容错与安全防护技术

分布式系统在关键基础设施(如轨道交通、智能电网)中面临网络延迟和恶意节点的双重挑战。拜占庭容错(BFT)技术通过算法保证系统在存在故障节点时仍能达成一致,是保障系统安全的核心机制。GEOSHIELD创新性地结合概率化网络延迟测量和TGS动态信任评分,实现了不依赖可信硬件的拜占庭 resilience。该技术通过建立节点行为的信用档案,动态识别恶意行为,在保证安全性的同时最大化系统可用性。实验证明,即使在自适应攻击策略下,GEOSHIELD仍能保持系统95.6%的正常运行时间,为CPS系统提供了可靠的安全防护

weixin_31766003的博客 348

Remoting基本原理及其扩展机制(ZZ)

 .NET Remoting是.NET平台上允许存在于不同应用程序域中的对象相互知晓对方并进行通讯的基础设施。调用对象被称为客户端,而被调用对象则被称为服务器或者服务器对象。简而言之,它就是.NET平台上实现分布式对象系统的框架。传统的方法调用是通过栈实现,调用方法前将this指针以及方法参数压入线程栈中,线程执行方法时将栈中的参数取出作为本地变量,经过一番计算后,将方法的返回结果压入栈中

虫子的专栏 1720

FI 应计对象的创建和摊销

创建/修改:ACACTREE01/ACACTREE02 应计对象的过账:ACACPOSTING

nancyln9711的博客 904

Ubuntu无桥接模式或连不上网(详细解决方法

目录 问题1:Ubuntu没有未桥接的主机网络适配器 解决方法 1.打开VMware安装目录下的文件 ​编辑2.右键安装以上三个文件 3.打开网络状态属性,找到VMware bridgeProtocol,点击安装 问题2.Ubuntu桥接模式连不上网 1.win+r打开cmd终端,输入ipconfig /all 2.记录以下数据 3.打开VMware网络设置 问题1:Ubuntu没有未桥接的主机网络适配器 VMWare安装之后,虚拟网络一直使用默认配置 VMnet0为...

m0_65592409的博客 6062

Microsoft .Net Remoting系列专题之三:Remoting事件处理全接触

前言:在Remoting中处理事件其实并不复杂,但其中有些技巧需要你去挖掘出来。正是这些技巧,仿佛森严的壁垒,让许多人望而生畏,或者是不知所谓,最后放弃了事件在Remoting的使用。关于这个主题,在网上也有很多讨论,相关的技术文章也不少,遗憾的是,很多文章概述的都不太全面。我在研究Remoting的时候,也对事件处理发生了兴趣。经过参考相关的书籍、文档,并经过反复的试验,深信自己能够把这个问题阐

冯钰 的专栏 5842

华硕ROG玩家国度安装Ubuntu双系统避坑指南:安全启动密钥那些事儿

本文详细解析了在华硕ROG玩家国度设备上安装Ubuntu双系统时,如何正确处理BIOS中的安全启动(Secure Boot)与密钥管理,避免常见的引导失败和Windows系统无法启动问题。指南提供了从数据备份、启动盘制作到BIOS精细设置(如将OS Type改为Other OS而非简单关闭Secure Boot)以及分区规划的完整流程,确保两个系统都能稳定共存。

weixin_29219189的博客 756

Microsoft .Net Remoting系列专题之三

Microsoft .Net Remoting系列专题之三 Microsoft .Net Remoting系列专题之三:Remoting事件处理全接触 前言:在Remoting中处理事件其实并不复杂,但其中有些技巧需要你去挖掘出来。正是这些技巧,仿佛森严的壁垒,让许多人望而生畏,或者是不知所谓,最后放弃了事件在Remoting的使用。关于这个主题,在网上也有很多讨论,相关的技术文章也不少,遗憾

bluniu的专栏 1815

开源大模型本地部署实战:Llama、DeepSeek、Qwen选型与工程落地指南

大语言模型(LLM)本地部署已成为AI工程化核心环节,其本质不是比拼参数量或榜单分数,而是考察模型架构、推理引擎、量化支持、IDE集成与多模态扩展能力的系统性适配。Llama以纯净Transformer结构成为通用底座,依赖llama.cpp和GGUF量化实现跨平台轻量推理;DeepSeek深度优化代码与数学推理,通过原生OpenAPI、FlashAttention-2及tensor parallelism显著降低API延迟;Qwen则采用模块化设计,支持视觉编码器(Qwen-VL)、生物计算(Qwen-B

weixin_29952383的博客 396

Ansys Lumerical实战:5步搞定Mach-Zehnder调制器多物理场仿真(附眼图分析技巧)

本文详细介绍了使用Ansys Lumerical进行行波马赫-曾德尔调制器多物理场仿真的完整流程。通过CHARGE、MODE和INTERCONNECT三大模块的协同工作,从电学参数提取、光学射频特性分析到系统级眼图评估,分步解析了高效仿真与性能优化的核心技巧,为硅光调制器设计提供了实战指南。

weixin_29056781的博客 547

Remoting事件机制续

(1)关闭一个客户端以后会影响其他的客户端事件原因:客户端没有取消事件订阅就关闭了,触发事件的时候找不到事件订阅者解决:遍历委托链,找到异常的对象,从委托链中卸下(2)服务器端对客户端广播,客户端能收到其他客户端的事件处理信息原因:使用了Singleton模式,共享远程对象解决:因为需要远程对象有状态且不共享实例,所以只有客户端激活可以选择修改后的服务端:using System; usi

冷枫@优快云 1464

OpenSceneGraph编译、安装、开发环境

详细描述WIndows 10下使用Visual Studio 2019编译OpenSceneGraph 3.6.5的操作流程

国产CAx(CAD/CAE/CAM)软件研发 8774

C# Remoting例子

4-23 https://www.cnblogs.com/zhengyun_ustc/archive/2006/06/09/remoting_InvalidCredentialException.html 今天看了一篇C# Remoting的一个简单例子,博主简单的介绍了remoting,目前所开发的系统也用到了remoting,特意重温了下系统,发觉其实也就那么回事情,服务器端定...

dayao8092的博客 216

Spring Boot入门(13):Mybatis-Plus之条件构造器使用手册:精通让你快速提高查询效率的技巧!

化繁为简,MP 中条件构造器的使用,极其详细.

**My Coding Family** 3万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

C# Remoting的一个简单例子

 C# Remoting的一个简单例子 .Net对于远程调用提供了两种方法:Remoting和WebService。WebService现在是如火如荼,特别是有一种比较流行的架构:Winform+WebService(Java、.Net),我曾经做过的一个项目就是这样子的,分布式、跨平台、极佳的用户体验,这三者结合起来是不是很诱人?不过,这里我只说Remoting,Remoting具有以下

bmoon的专栏 1万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

.Net中Remoting通信机制

Remoting通信机制 Remoting介绍 主要元素 通道类型 激活方式 对象定义 Remoting介绍 什么是Remoting,简而言之,我们可以将其看作是一种分布式处理方式。 从微软的产品角度来看,可以说Remoting就是DCOM(分布式组件对象模型,分布式组件对象模式)的一种升级,它改善了很多功能,并极好的融合到.Net平台下。Mic

JiYF大男孩 2795

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

一步一步学Remoting之六:事件(1)

原文转自http://www.cnblogs.com/lovecherry/archive/2005/05/24/161437.html 事件 类或对象可以通过事件向其他类或对象通知发生的相关事情。发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订户”。 具体参见msdn相关章节:http://msdn.microsoft.com/zh-cn/library...

amkr21253的博客 147

remoting教学四:remoting的事件

remoting教学四:remoting的事件     现在,为了更好的表现事件,我们将客户端和服务器都用winform来表现。     在如下的例子中,将会产生一个服务器端事件和一个客户端事件。 RemoteObject using System; using System.Windows.Forms; using System.Colle

900

利用Remoting实现异步队列机制

<!-- alimama_pid="mm_10249644_1605763_4929893"; alimama_titlecolor="0000FF"; alimama_descolor ="000000"; alimama_bgcolor="FFFFFF"; alimama_bordercolor="E6E6E6"; alimama_linkcolor="0080

1084
上一篇: Remoting之异步操作模式
下一篇: Remoting事件机制续
JavaProgramers
博客等级 码龄22年 660粉丝 304原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值