积极答复者
Remoting 获取远程对象返回结果判断

问题
答案
-
由于远程对象会被自动创建 Proxy 类,所以无论如何,Activator.GetObject 会得到非空对象。还有,GetObject 的行为会因为远程对象的不同而可能不同,比如是否是 MarshalByRef 或者 ByValue。
详细情况可以参考 MSDN 的 Activator 帮助文档。
Mark Zhou- 已标记为答案 Leo Liu - MSFTModerator 2011年4月25日 2:35
-
谢谢了。但是还有个问题请教下。
Server:
class ServerProvide { BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); IDictionary properties = new Hashtable(); ObjRef objRefWellKnow; MainServiceManager MServiceManager = new MainServiceManager(); public ServerProvide( ) { serverProvider.TypeFilterLevel = TypeFilterLevel.Full; properties["port"] = 9899; } public void Start() { TcpChannel tcpChannel = new TcpChannel(properties, clientProvider, serverProvider);//tcp通道 ChannelServices.RegisterChannel(tcpChannel, true); objRefWellKnow = RemotingServices.Marshal(MServiceManager, "IMainServiceManager"); }}
Client:
public class RemotingProvide { static RemotingProvide _remotingProvide; static object _Key = new object(); BinaryServerFormatterSinkProvider serverProvider; BinaryClientFormatterSinkProvider clientProvider; IDictionary props ; TcpChannel tcpChannelMainService; int port = 9820; private RemotingProvide() { //使用TCP通道得到远程对象,不用监听 serverProvider = new BinaryServerFormatterSinkProvider(); clientProvider = new BinaryClientFormatterSinkProvider(); serverProvider.TypeFilterLevel = TypeFilterLevel.Full; props = new Hashtable(); XX: props["port"] = port; props["name"] = "IMService"; try { tcpChannelMainService = new TcpChannel(props, clientProvider, serverProvider); } catch { port++; goto XX; } ChannelServices.RegisterChannel(tcpChannelMainService, true); } public static RemotingProvide GetInstance() { if (_remotingProvide == null) { lock (_Key) { if (_remotingProvide == null) { _remotingProvide = new RemotingProvide(); } } } return _remotingProvide; } public IMainServiceManager GetRemotMainServiceManager(string ip, int port) { IMainServiceManager _manager=null; _manager = (IMainServiceManager)Activator.GetObject(typeof(IMainServiceManager), "tcp://" + ip + ":" + port.ToString() + "/IMainServiceManager"); return _manager; } }
这个是我服务端和客户端类似的代码,因为我服务端已启动就有MainServiceManager 对象存在,执行相关的业务功能。
客户端是一个管理界面,客户端主要是为了操作管理服务端的MainServiceManager对象。如果客户端管理界面存在,MainServiceManager的一些运行信息和日志会通过事件
告知客户端。
但是现在主要的问题是:客户端执行远程对象的一些操作后,过一会儿,远程对象会被回收。如果使用租约的话但是有只能适用于客户端激活和SingleCall.
怎么才能解决我这种情况的续约。
-
有两种方法您可以不妨一试。第一,在服务器上,用 GC.KeepAlive 把需要保留的未包装对象标记成不回收。二,在客户端采用 PerCall 的方式,每次调用远程对象时创建新的包装类实例。
这两种方法各有优缺点。比如,GC.KeepAlive 会导致托管堆上的死角,它会影响 GC 在 Compact 过程中性能,PerCall 的话通信成本很高,每次都会重新建立 TCP 连接。如果您需要 TCP 长连接的话,我建议您可以采用 WCF Service,它提供的 ChallelFactory 是带缓存的,不会导致远程对象回收问题。
Mark Zhou- 已标记为答案 剑仙红世 2011年5月30日 3:43
全部回复
-
由于远程对象会被自动创建 Proxy 类,所以无论如何,Activator.GetObject 会得到非空对象。还有,GetObject 的行为会因为远程对象的不同而可能不同,比如是否是 MarshalByRef 或者 ByValue。
详细情况可以参考 MSDN 的 Activator 帮助文档。
Mark Zhou- 已标记为答案 Leo Liu - MSFTModerator 2011年4月25日 2:35
-
谢谢了。但是还有个问题请教下。
Server:
class ServerProvide { BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); IDictionary properties = new Hashtable(); ObjRef objRefWellKnow; MainServiceManager MServiceManager = new MainServiceManager(); public ServerProvide( ) { serverProvider.TypeFilterLevel = TypeFilterLevel.Full; properties["port"] = 9899; } public void Start() { TcpChannel tcpChannel = new TcpChannel(properties, clientProvider, serverProvider);//tcp通道 ChannelServices.RegisterChannel(tcpChannel, true); objRefWellKnow = RemotingServices.Marshal(MServiceManager, "IMainServiceManager"); }}
Client:
public class RemotingProvide { static RemotingProvide _remotingProvide; static object _Key = new object(); BinaryServerFormatterSinkProvider serverProvider; BinaryClientFormatterSinkProvider clientProvider; IDictionary props ; TcpChannel tcpChannelMainService; int port = 9820; private RemotingProvide() { //使用TCP通道得到远程对象,不用监听 serverProvider = new BinaryServerFormatterSinkProvider(); clientProvider = new BinaryClientFormatterSinkProvider(); serverProvider.TypeFilterLevel = TypeFilterLevel.Full; props = new Hashtable(); XX: props["port"] = port; props["name"] = "IMService"; try { tcpChannelMainService = new TcpChannel(props, clientProvider, serverProvider); } catch { port++; goto XX; } ChannelServices.RegisterChannel(tcpChannelMainService, true); } public static RemotingProvide GetInstance() { if (_remotingProvide == null) { lock (_Key) { if (_remotingProvide == null) { _remotingProvide = new RemotingProvide(); } } } return _remotingProvide; } public IMainServiceManager GetRemotMainServiceManager(string ip, int port) { IMainServiceManager _manager=null; _manager = (IMainServiceManager)Activator.GetObject(typeof(IMainServiceManager), "tcp://" + ip + ":" + port.ToString() + "/IMainServiceManager"); return _manager; } }
这个是我服务端和客户端类似的代码,因为我服务端已启动就有MainServiceManager 对象存在,执行相关的业务功能。
客户端是一个管理界面,客户端主要是为了操作管理服务端的MainServiceManager对象。如果客户端管理界面存在,MainServiceManager的一些运行信息和日志会通过事件
告知客户端。
但是现在主要的问题是:客户端执行远程对象的一些操作后,过一会儿,远程对象会被回收。如果使用租约的话但是有只能适用于客户端激活和SingleCall.
怎么才能解决我这种情况的续约。
-
有两种方法您可以不妨一试。第一,在服务器上,用 GC.KeepAlive 把需要保留的未包装对象标记成不回收。二,在客户端采用 PerCall 的方式,每次调用远程对象时创建新的包装类实例。
这两种方法各有优缺点。比如,GC.KeepAlive 会导致托管堆上的死角,它会影响 GC 在 Compact 过程中性能,PerCall 的话通信成本很高,每次都会重新建立 TCP 连接。如果您需要 TCP 长连接的话,我建议您可以采用 WCF Service,它提供的 ChallelFactory 是带缓存的,不会导致远程对象回收问题。
Mark Zhou- 已标记为答案 剑仙红世 2011年5月30日 3:43