这是我在谷歌上搜索了很多天试图为我的问题找到明确答案后的最后手段。
我已经创建了一个 Windows 服务、一个 Windows 窗体和一个 Remoting 对象(全部在 C# 中)。我正在使用 Remoting 对象通过事件在服务和表单之间进行通信。
这是对象之间典型交互的简化示例:
- AdminForm 调用 RemoteObject 的 方法 RequestLoadForm()
- RemoteObject 触发一个事件,AdminService 正在监听
- AdminService 收到事件警报,并在 RemoteObject 上调用 LoadFormData(string data)
- RemoteObject 触发一个事件,AdminForm 正在监听
- AdminForm 收到事件警报,并可以使用字符串数据在 AdminForm 的控件上设置值
这一切都很好,在前 5 分钟左右的时间里,一切都相互作用得很好。在那之后,对象之间的连接以某种方式被切断,我无法再在对象之间进行通信。
修复该问题的第一个尝试是重写 InitializeLifetimeService 方法以返回 null。这没有帮助(尽管它可以避免任何 future 的租赁问题)。
第二次尝试是让我的 AdminForm 和 AdminService 成为 RemoteObject 的赞助商,并将它们设置为续订该对象的租约。再一次,没有解决问题。
在我的各种谷歌搜索中,我发现有人提到了一些关于事件处理程序被垃圾收集的事情。我不确定这是否是问题所在,但我想我会提到它。
这是连接空闲超过 5 分钟后弹出的错误:
System.Runtime.Remoting.RemotingException 未被用户代码处理
Message="找不到请求的服务"
Source="System.Runtime.Remoting"
现在,奇怪的是它发生在 AdminService 端。 AdminForm 可以很好地调用 RemoteObject 上的方法。这弹出事件,然后 AdminService 看到这个事件,并尝试调用 RemoteObject 的方法 LoadFormData(string data),这就是抛出异常的地方.
Google 搜索让我筋疲力尽,因为我似乎找不到修复它所需的东西。
最佳答案
我面临着相当相似的问题。希望以下观察和解决方案也适用于任何有类似问题的人。
让对象 A 与对象 B 跨应用域通信,而对象 B 将通过一些事件处理程序回调对象 A。对象A和B都继承自MarshalByRefObject,实现跨应用域的相互调用。
对象 B 覆盖 InitializeLifeTimeService 以返回 null 以实现无限租约。但是,连接仍会在程序启动后约 5 分钟(remoting 默认初始租约时间)过期。
一个重要的观察是来自对象A的调用仍然会成功执行,但是当对象B回调时,异常在对象B上引发。显然,连接到期发生在对象A的回调代理上,而不是与我们想象的相反。
因此,快速回答,确保对象 A 和 B 都覆盖 InitializeLifeTimeService 以返回 null。这将解决问题,至少对我而言是这样。
只是一些额外的东西,当连接过期时,并不一定意味着连接的对象被垃圾收集。租约到期将导致代理断开连接,但实际对象可能仍存在于相应的应用程序域中。如果您将租约到期时间与被 GC 处理的对象保持一致,那么您可能会看不到全貌。
关于c# - 为什么我的 C# Remoting 对象超时,即使 Lifetime 返回 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6133122/