MarshalByRefObject变为“在服务器上断开连接”。即使赞助 [英] MarshalByRefObject becoming "disconnected at server" even while sponsored

查看:145
本文介绍了MarshalByRefObject变为“在服务器上断开连接”。即使赞助的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个支持mod的游戏,为了安全起见,我将把mod沙盒放入与游戏引擎分开的AppDomain中(这样我就可以将mod的功能与引擎分开限制)。但是,脚本域中的对象被引擎保留了引用,以确保太早收集垃圾,而我却遇到了这样的异常:

I am writing a game which supports mods, for safety I am sandboxing the mods into a separate AppDomain from the game engine (so I can restrict the capabilities of mods separately from the engine). However, objects in the scripting domain which the engine keeps a reference to keep getting garbage collected too early and I get an exception like this:


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

Object '/30b08873_4929_48a5_989c_e8e5cebc601f/lhejbssq8d8qsgvuulhbkqbo_615.rem' has been disconnected or does not exist at the server.



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

// Take in a "script reference" which is basically just the name of a type in the scripting domain
public Reference<T> Dereference<T>(ScriptReference reference) where T : MarshalByRefObject
{
    // Create a remote instance of this type
    T instance = (T)RemoteFunc.Invoke<ScriptReference, object>(_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<T>(instance, reference.TypeName, reference.Name);
}

想法是 Reference< T> 是对象的赞助者,只要它保持活动状态,远程域中的对象也将保持活动状态。这就是问题所在,我正在通过对象的引用访问对象,但是仍然出现服务器断开连接异常。这是我对 Reference< T> 的实现:

The idea is that Reference<T> is the sponsor for the object and as long as it stays alive the object in the remote domain will also stay alive. This is where the problem lies, I am accessing objects through their reference and yet I still get the "disconnected at server" exception. Here is my implementation of Reference<T>:

public sealed class Reference<T>
    : 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);
    }

    /// <summary>
    /// 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
    /// </summary>
    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;
        }
    }
}

我在做什么错导致我的对象死掉了,即使有实时的 Reference< T>

What am I doing wrong to cause my objects to die even whilst there is a live Reference<T> to them?

推荐答案

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

Use the ClientSponsor class that is built into .NET. It is very stable and simplistic.

这是大多数人在跨AppDomain进行工作时会想到的。您的实现看起来不错,但可能很简单,例如 SponsorTime()没有从配置中返回正确的值。

It's what most people turn to when working across AppDomains. Your implementation looks fine, but could be as simple as your SponsorTime() not returning the correct value from the config.

这篇关于MarshalByRefObject变为“在服务器上断开连接”。即使赞助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆