“对象已断开连接或在服务器上不存在”例外

| 我需要在我的应用程序中使用跨应用程序域调用,有时我会遇到以下RemotingException:   服务器\ /2fa53226_da41_42ba_b185_ec7d9c454712/ygiw+xfegmkhdinj7g2kpkhc_7.rem \已断开连接或在服务器上不存在。 目标对象仍然存在,我已经检查了它。 UPD我已经在目标对象的终结器中设置了断点,但是它从未命中。因此,该对象是活动的,并且没有被GC处理。     
已邀请:
        这可能是因为服务器端的本地垃圾收集器收集了对象。您可以通过续租来避免这种情况。您可以在以下文章中阅读有关此内容的更多信息: 通过租赁和赞助管理远程.NET对象的生命周期 由内而外的CLR:管理对象生命周期 更新:不幸的是,2008年或更早版本的《 MSDN杂志》不再可以在线浏览,而只能作为.chm文件下载,您必须将其下载到本地计算机上。以前的问题可以在以下位置找到: 通过租赁和赞助管理远程.NET对象的生命周期,于2003年12月发行 CLR Inside Out:2007年11月发行的“管理对象生命周期”     
        这是因为服务器端的生命周期管理会在对象的租约到期时断开连接,以允许GC收集对象。如果您尝试从客户端使用它,即使服务器上尚未对其进行GC(例如,因为仍然有对其的另一引用),但您的租约已过期,您仍将获得异常。这是为了避免不可预测的行为。可接受的答案为如何正确管理远程.NET对象的生存期提供了很好的参考。     
        我遇到了同样的问题,并在许多StackOverflow帖子的帮助下搜索了多个小时。 我终于找到了完整的问题。 我必须使用发起人来维持我的MarshalByRefObject存活。 然后,我遇到了与@ user626528相同的问题:对象仍然存在,但是我遇到了异常。实际上,我需要\“ sponsor \”所有\“ TransparentProxy \”实例,而不仅仅是主要实例:我在SandBox(另一个AppDomain)中创建的主要对象返回对其他MarshalByRefObjects的引用。 这是完整的解释和用例: 我的类“ Loader”是从MarshalByRefObject继承的,并且通过ISponsor类使它保持活动状态。我知道.NET中存在\“ ClientSponsor \”,但是我无法确定是否以及何时调用Renewal(),因此我在StackOverflow社区的帮助下制作了我的课程(阅读代码注释):
/// <see cref=\"https://stackoverflow.com/questions/18680664/remoting-sponsor-stops-being-called\"/>
public class RemotingSponsor : MarshalByRefObject, ISponsor, IDisposable
{
    /*
     * @CoryNelson said :
     * I\'ve since determined that the ILease objects of my sponsors 
     * themselves are being GCed. They start out with the default 5min lease 
     * time, which explains how often my sponsors are being called. When I 
     * set my InitialLeaseTime to 1min, the ILease objects are continually        
     * renewed due to their RenewOnCallTime being the default of 2min.
     * 
     */ 

    ILease _lease;

    public RemotingSponsor(MarshalByRefObject mbro)
    {
        _lease = (ILease)RemotingServices.GetLifetimeService(mbro);
        if (_lease == null) throw new NotSupportedException(\"Lease instance for MarshalByRefObject is NULL\");
        _lease.Register(this);
    }

    public TimeSpan Renewal(ILease lease)
    {
        Debug.WriteLine(\"RemotingSponsor.Renewal called\");
        return this._lease != null ? lease.InitialLeaseTime : TimeSpan.Zero;
    }


    public void Dispose()
    {
        if (_lease != null)
        {
            _lease.Unregister(this);
            _lease = null;
        }
    }

    public override object InitializeLifetimeService()
    {
        /*
         *
         * @MatthewLee said:
         *   It\'s been a long time since this question was asked, but I ran into this today and after a couple hours, I figured it out. 
         * The 5 minutes issue is because your Sponsor which has to inherit from MarshalByRefObject also has an associated lease. 
         * It\'s created in your Client domain and your Host domain has a proxy to the reference in your Client domain. 
         * This expires after the default 5 minutes unless you override the InitializeLifetimeService() method in your Sponsor class or this sponsor has its own sponsor keeping it from expiring.
         *   Funnily enough, I overcame this by returning Null in the sponsor\'s InitializeLifetimeService() override to give it an infinite timespan lease, and I created my ISponsor implementation to remove that in a Host MBRO.
         * Source: https://stackoverflow.com/questions/18680664/remoting-sponsor-stops-being-called
        */
        return (null);
    }
}
然后我像这样使用“自定义赞助商”:
// Loader and Container for MarshalByRefObject in another domain
 public class PluginFile : IDisposable
 {
           private RemotingSponsor _sponsor; // Keep instance not to have Sponsor Garbage Collected
           private AppDomain _sandbox;
           private ICustomPlugin[] _plugins; // I do not store real instances of Plugins, but a \"CustomPluginProxy\" which is known both by main AppDomain and Plugin AppDomain.

    // Constructor : load an assembly file in another AppDomain (sandbox)
    public PluginFile(System.IO.FileInfo f, AppDomainSetup appDomainSetup, Evidence evidence)
    {
        Directory = System.IO.Path.GetDirectoryName(f.FullName) + @\"\\\";
        _sandbox = AppDomain.CreateDomain(\"sandbox_\" + Guid.NewGuid(), evidence, appDomainSetup);

        _sandbox.Load(typeof(Loader).Assembly.FullName);

        // - Instanciate class \"Loader\" INSIDE OTHER APPDOMAIN, so we couldn\'t use new() which would create in main AppDomain.
        _loader = (Loader)Activator.CreateInstance(
            _sandbox,
            typeof(Loader).Assembly.FullName,
            typeof(Loader).FullName,
            false,
            BindingFlags.Public | BindingFlags.Instance,
            null,
            null,
            null,
            null).Unwrap();

        // - Load plugins list for assembly
        _plugins= _loader.LoadPlugins(f.FullName); 


        // - Keep object created in other AppDomain not to be \"Garbage Collected\". I create a sponsor. The sponsor in registed for object \"Lease\". The LeaseManager will check lease expiration, and call sponsor. Sponsor can decide to renew lease. I not renewed, the object is garbage collected.
        // - Here is an explanation. Source: https://stackoverflow.com/questions/12306497/how-do-the-isponsor-and-ilease-interfaces-work
        _sponsor = new RemotingSponsor(_loader);

       // Here is my SOLUTION after many hours ! I had to sponsor each MarshalByRefObject (plugins) and not only the main one that contains others !!!
       foreach (ICustomPlugin plugin in Plugins) 
        {
            ILease lease = (ILease)RemotingServices.GetLifetimeService((PluginProxy)plugin);
            lease.Register(_sponsor); // Use the same sponsor. Each Object lease could have as many sponsors as needed, and each sponsor could be registered in many Leases.
        }
    }

 }
PluginProxy类型具有对实际插件类型的引用。实际上,PluginProxy是在Plugin AppDomain中实例化的,并返回到主AppDomain,以允许它调用Plugins,即使它忽略了它们的真实类型。因此,必须从主AppDomain访问的PluginProxy必须进行序列化以突破AppDomains限制。我遇到了一个问题,因为我没有赞助这些MarshalByRefObject(s):
 /// <see cref=\"https://stackoverflow.com/questions/4185816/how-to-pass-an-unknown-type-between-two-net-appdomains\"/>
    [Serializable]
    public class PluginProxy : MarshalByRefObject, ICustomPlugin
    {
        private ICustomPlugin _hostedPlugin;            

        /// <summary>
        /// Parameterless constructor for deserialization 
        /// </summary>
        public PluginProxy()
        {             
        }

        ~PluginProxy()
        {
            Debug.WriteLine(\"DESTRUCTOR ~PluginProxy\");
        }

        /// <summary>
        /// Constructor reserved from real Plugin type
        /// </summary>
        /// <param name=\"name\"></param>
        public PluginProxy(ICustomPlugin hostedPlugin)
        {
            _hostedPlugin = hostedPlugin;
        }

        public PluginName Name => _hostedPlugin.Name;

        public PluginResult Execute(PluginParameters parameters, PluginQuery query)
        {
            return(_hostedPlugin.Execute(parameters, query));
        }
    }
这是一堆很难解决的问题,希望对您有所帮助! 参考文献: MSDN:ILease接口 MSDN:ObjRef类 Microsoft:如何使用Visual C#通过引用将对象封送至远程服务器 StackOverflow:远程发起者不再被调用 StackOverflow:ISponsor和ILease接口如何工作? StackOverflow:如何在两个.NET AppDomain之间传递未知类型? StackOverflow:AppDomain和MarshalByRefObject的生存时间:如何避免RemotingException? StackOverflow:即使赞助,MarshalByRefObject也会“在服务器上断开连接”     
        这发生在我们身上,因为我们在一个类中有一个静态变量,类型为AppDomain。该类在长时间运行的Windows服务中使用。 AppDomain有一个InitializeLifetimeService方法,需要像这样重写:
public override object InitializeLifetimeService(){
    return null;
}
我们一直在使用它作为私有变量,它为自定义的外部逻辑加载和卸载了一些dll。 答案已从此处获取:msdn答案 由于我们无法在生产时更改此设置,因此以折衷的方式进行了折衷,即以随机间隔重新启动Windows服务,该间隔短于静态AppDomain变量的生存期,通过反复试验,我们发现该间隔为几天。 这个问题也有助于弄清有关生命周期的一些问题:stackoverflow-question     
以我为例,问题是客户端计算机中有一个活动的虚拟网络适配器,禁用了该虚拟网络适配器,此问题已解决     
        就我而言,这是在存储在Local5 happen项目内的
App_Data
文件夹中的SQL LocalDB发生的。每当我尝试使用Package Console运行ѭ6来通过迁移初始化我的Entity Framework数据库时,都不会发生任何事情。然后过了一会儿,我得到了那个错误。 我通过修改
App_Data
的文件权限来解决此问题。一旦修复,瞧,它就起作用了。     
        这个问题已经在StackOverflow上得到了非常详细的回答。 TL / DR: 如果要让Singleton语义覆盖
InitializeLifetimeService
以返回null 使用ѭ9可使您的物体存活更长的时间。     

要回复问题请先登录注册