MarshalByRefObject即使在赞助时也会“在服务器上断开连接”

我正在编写一个支持mods的游戏,为了安全起见,我将mods沙盒化为游戏引擎中的单独AppDomain(因此我可以将mods的function与引擎分开限制)。 但是,脚本域中的对象引擎保持引用以便过早收集垃圾并且我得到如下的exception:

对象’/30b08873_4929_48a5_989c_e8e5cebc601f/lhejbssq8d8qsgvuulhbkqbo_615.rem’已断开连接或在服务器上不存在。

在服务器端,我正在创建这样的对象(使用AppDomainToolkit :

// Take in a "script reference" which is basically just the name of a type in the scripting domain public Reference Dereference(ScriptReference reference) where T : MarshalByRefObject { // Create a remote instance of this type T instance = (T)RemoteFunc.Invoke(_pluginContext.Domain, reference, r => { var t = Type.GetType(r.TypeName, true, false); return Activator.CreateInstance(t); }); //Return a reference which keeps this object alive until disposed return new Reference(instance, reference.TypeName, reference.Name); } 

想法是Reference 是对象的赞助商,只要它保持活跃状态​​,远程域中的对象也将保持活跃状态​​。 这就是问题所在,我通过他们的引用访问对象,但我仍然得到“在服务器上断开连接”的exception。 这是我对Reference 的实现

 public sealed class Reference : IDisposable where T : MarshalByRefObject { private InnerSponsor _sponsor; public T RemoteObject { get { return _sponsor.RemoteObject; } } public string TypeName { get; private set; } public string Name { get; private set; } public Reference(T obj, string typeName = null, string name = null) { TypeName = typeName; Name = name; _sponsor = new InnerSponsor(obj); } ~Reference() { if (_sponsor != null) _sponsor.Dispose(); _sponsor = null; } public void Dispose() { _sponsor.Dispose(); GC.SuppressFinalize(this); } ///  /// Inner sponsor is the actual sponsor (and is kept alive by the remoting system). /// If all references to Reference are lost, it will dispose the sponsor in its destructor ///  private sealed class InnerSponsor : MarshalByRefObject, ISponsor, IDisposable { private readonly ILease _lease; private bool _isDisposed; public readonly T RemoteObject; private bool _isUnregistered = false; public InnerSponsor(T obj) { RemoteObject = obj; _lease = (ILease)obj.GetLifetimeService(); _lease.Register(this, SponsorTime()); } public TimeSpan Renewal(ILease lease) { if (lease == null) throw new ArgumentNullException("lease"); if (_isDisposed) { if (!_isUnregistered) { _lease.Unregister(this); _isUnregistered = true; } return TimeSpan.Zero; } return SponsorTime(); } private static TimeSpan SponsorTime() { return TimeSpan.FromMilliseconds(/*Some value fetched from configuration*/); } public void Dispose() { _isDisposed = true; } } } 

我有什么错误导致我的物体死亡,即使有一个实时参考给他们?

使用.NET中内置的ClientSponsor类。 它非常稳定和简单。

这是大多数人在AppDomains上工作时所转向的。 您的实现看起来很好,但可能就像您的SponsorTime()没有从配置中返回正确的值一样简单。

我在StackOverflowpost中发现了一些似乎更简单的解决方案。

它包括告诉对象有无限的生命时间,这样做:

 [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)] public override object InitializeLifetimeService() { return null; } 

这个解决方案不是一致的,但这个post给我们带来了更多有价值的答案。