在 .Net Remoting 中使用单例

Posted

技术标签:

【中文标题】在 .Net Remoting 中使用单例【英文标题】:Working with singletons in .Net Remoting 【发布时间】:2010-10-18 15:51:40 【问题描述】:

我通过远程处理暴露的单例类有点问题。在我的服务器中,我有:

TcpChannel channel = new TcpChannel( Settings.Default.RemotingPort );
ChannelServices.RegisterChannel( channel, false );
RemotingConfiguration.RegisterWellKnownServiceType( 
    typeof( RemotableObject ), "RemotableObject", 
    WellKnownObjectMode.Singleton );

RemotableObject 是一个继承 MarshalByRefObject 的单例对象。

我的客户通过以下方式连接到它:

remoteObject = (RemotableObject)Activator.GetObject(
    typeof( RemotableObject ),
    string.Format( "tcp://0:1/RemotableObject", serverIP, serverPort ) );

就远程处理而言,一切都很好,但是当我像这样访问服务器代码中的单例对象时:

int someValue = RemotableObject.Instance.SomeDynamicValue;

它访问的实例与客户端不同。我还验证了 RemotableObject 中的私有构造函数在调试时被命中两次。

如果我通过服务器代码中的远程处理获取 RemotableObject 的实例,我可以获得所需的行为,但是有没有一种方法可以让我从服务器访问与我的客户端相同的对象,而无需远程处理开销?

【问题讨论】:

【参考方案1】:

如果我了解您的需求,(您希望对象存在于服务器上,但您希望所有客户端调用都在服务器上获取对象的相同实例,并且您还希望在服务器代码中调用获得相同的实例?)

那么,如果您的服务器是“ServerName”,并且它正在侦听端口 nnnn,并且 Uri 为“MyMsgEndpointUri”,那么您将 Uri 定义为:

var MesgUri = "tcp://ServerName:nnnn/MyMsgEndpointUri"; 

在您的服务器中,通过以下方式初始化端点:

RemotingServices.Marshal([singletonInstance], MesgURI);  

而不是RegisterWellKnownServiceType();

另外,在代表单例的类中,请记住使用 null 操作覆盖 InitializeLifetimeService 属性...否则单例对象将在某个时候收集垃圾...

public override object InitializeLifetimeService()  return (null); 

从服务器,只需调用你的单例类的静态工厂方法来访问那个单例实例...不要使用远程调用...

【讨论】:

MesgURI 的值应该是多少?我的 tcp 通道称为 UsersTcp,我尝试使用该名称和 uri:tcp://localhost:5000/UserTcp,两者都给我一个 no service found 错误。 应该是tcp://[ServerName]:[PortNumber]/MesgUri,如tcp://MYSERVERNAME:5212/UsersTcp 调用激活对象时,使用Activator.GetObject(),应该是tcp://[ServerName]:[PortNumber]/MesgUri,如tcp://MYSERVERNAME:5212/UsersTcp。如果远程对象的类名为 RemoteClass 并且它实现的接口(由远程服务公开的接口是 IRemoteClass 则调用应如下所示:var myNewObject = (IRemoteClass)Activator.GetObject(typeof(RemoteClass), "tcp://MYSERVERNAME:5212/UsersTcp");【参考方案2】:

我从未尝试从服务器端调用 Activator.GetObject,但这应该返回客户端正在使用的相同实例。但是,你仍然会得到一个代理。

【讨论】:

【参考方案3】:

没有。

在服务器端没有办法读取客户端的内存。

【讨论】:

以上是关于在 .Net Remoting 中使用单例的主要内容,如果未能解决你的问题,请参考以下文章

.Net remoting方法实现简单的在线升级(上篇:更新文件)

.NET2.0 Remoting - 为啥需要注册 ClientChannel?

.Net Remoting,防火墙问题

.net core 2.0学习笔记:Remoting核心类库RealProxy迁移

在 IIS 7.5 中托管的 .Net Remoting 服务中,如何删除“Server : IIS/7.5”标记表单响应头

转载.NET Remoting学习笔记信道