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

发布于 2024-11-15 10:32:15 字数 267 浏览 3 评论 0原文

我需要在我的应用程序中使用跨应用程序域调用,有时我会遇到此 RemotingException:

对象“/2fa53226_da41_42ba_b185_ec7d9c454712/ygiw+xfegmkhdinj7g2kpkhc_7.rem”已断开连接或在服务器上不存在。

目标物体还活着,我已经检查过了。

UPD 我在目标对象的终结器中设置了断点,但它从未命中。因此,这个对象是活动的并且没有被 GC 回收。

I need to use cross-appdomain calls in my app, and sometimes I have this RemotingException:

Object '/2fa53226_da41_42ba_b185_ec7d9c454712/ygiw+xfegmkhdinj7g2kpkhc_7.rem' has been disconnected or does not exist at the server.

The target object is still alive, I have checked it.

UPD I've set breakpoint in the finalizer of the target object, and it never hits. Thus, this object is alive and wasn't GC'ed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

z祗昰~ 2024-11-22 10:32:15

这可能是因为服务器端的本地垃圾收集器收集了该对象。您可以通过续订租赁来防止这种情况发生。您可以在以下文章中阅读更多相关信息:

更新:不幸的是,2008 年或更早版本的 MSDN 杂志不再可以在线浏览,而只能以 .chm 文件形式浏览,您必须将其下载到本地计算机。以前的问题可以在以下位置找到:

That is probably because the local garbage collector at the server side collects the object. You can prevent that by renewing the leasing. You can read more about that in these articles:

Update: Unfortunately, the MSDN Magazine issues from 2008 or older are no longer browseable online, but only as .chm files that you have to download to your local machine. The previous issues can be found in:

ゞ记忆︶ㄣ 2024-11-22 10:32:15

这是因为服务器端的 Lifetime 管理会在对象的租约到期时断开该对象的连接,以允许 GC 来收集它。如果您尝试从客户端使用它,您将收到异常,即使它尚未在服务器上被 GC(例如,因为仍然有另一个引用)但租约已过期。这是为了避免不可预测的行为。已接受的答案为如何正确管理远程 .NET 对象的生命周期提供了很好的参考。

This is because the Lifetime management on the server side disconnects the object when its lease expires, to allow GC to collect it. If you try to use it from the client side, you will get an Exception, even if it has not been GC'd on the server yet (e.g. because there still is another reference to it) but the lease has expired. This is to avoid unpredictable behaviour. The accepted answer provides a good reference on how to correctly manage the lifetime of Remote .NET Objects.

聚集的泪 2024-11-22 10:32:15

我遇到了同样的问题,并且在许多 StackOverflow 帖子的帮助下搜索了很多个小时。

我终于找到了完整的问题。

  1. 我必须使用赞助商来维持我的 MarshalByRefObject 的活动。
  2. 然后我遇到了与 @user626528 相同的问题:对象还活着,但我有例外。事实上,我需要“赞助”所有“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,以允许它调用插件,即使它忽略插件的真实类型。因此,要从主 AppDomain 访问 PluginProxy,必须进行序列化以跨越 AppDomain 限制。我遇到了一个问题,因为我没有赞助这些 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));
        }
    }

这是一堆很难解决的问题,希望这会有所帮助!

参考文献:

I had the same problem and I searched for many hours with help of many StackOverflow posts.

I finally found the complete issue.

  1. I have to use a Sponsor to maintain my MarshalByRefObject alive.
  2. I then had the same problem than @user626528 : object is alive but I had the exception. In fact, I needed to "sponsor" ALL THE "TransparentProxy" instances, and not only the main one : my main Object created in SandBox (another AppDomain) returns references to other MarshalByRefObjects.

Here is the complete explanation and use case :

My class "Loader" inherits from MarshalByRefObject, and I keep it alive with a ISponsor class. I know "ClientSponsor" exists in .NET, but I had no way to determine if and when Renewal() is called, so I made my class with help of StackOverflow community (read code comments) :

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

And then I used this "custom sponsor" like this:

// 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.
        }
    }

 }

The PluginProxy type has a reference towards the real plugin type. Indeed, the PluginProxy is instanciated inside Plugin AppDomain, and returned to main AppDomain, to allow it to call Plugins even if it ignore their real type. So the PluginProxy, to be accessible from main AppDomain, have to be serialized to cross AppDomains limits. I had a problem because I didn't sponsored these 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));
        }
    }

It was a difficult bunch of problems to solve, hope this helps !

References:

柠栀 2024-11-22 10:32:15

这个问题已经详细回答了StackOverflow。 TL/DR:

  1. 如果您希望单例语义覆盖 InitializeLifetimeService 返回 null
  2. 使用 ClientSponsor< /code>让你的对象存活更长时间。

This question has been answered in great detail already on StackOverflow. TL/DR:

  1. If you want Singleton semantics override InitializeLifetimeService to return null
  2. Use ClientSponsor to keep you object alive longer.
本宫微胖 2024-11-22 10:32:15

这发生在我们身上,因为我们的一个类中有一个 AppDomain 类型的静态变量。该类用于长时间运行的 Windows 服务。
AppDomain 有一个 InitializeLifetimeService 方法,需要像这样重写:

public override object InitializeLifetimeService(){
    return null;
}

我们经常使用它作为私有变量,为自定义构建的外部逻辑加载和卸载一些 dll。
答案取自此处:msdn 回答

因为我们无法在生产时更改此设置,所以我们结束了折衷方案是以随机间隔重新启动 Windows 服务,该间隔短于静态 AppDomain 变量的生命周期,通过反复试验,我们发现它是几天。

这个问题还有助于澄清有关生命周期的一些事情: stackoverflow-question< /a>

This happened for us because we had a static variable in one of our classes that was of type AppDomain. The class was used in a long running windows service.
AppDomain has a InitializeLifetimeService method that needs to be overridden like this:

public override object InitializeLifetimeService(){
    return null;
}

We were constantly using this as the private variable that loaded and unloaded some dlls for custom built outside logic.
The answer has been taken from here: msdn answer

Because we were not able to change this at production time, we ended with a compromise of restarting the windows service at random intervals that are shorter than the lifetime of the static AppDomain variable which by trial and error we found that it is several days.

This question also helped clarify some things about lifetime: stackoverflow-question

七禾 2024-11-22 10:32:15

就我而言,问题是在客户端计算机中,有一个虚拟网络适配器处于活动状态,禁用虚拟网络适配器,问题就解决了

in my case, the problem was that in the client computer, there was an virtual network adapter active, disabling the virtual network adapters, the problem was solved

箹锭⒈辈孓 2024-11-22 10:32:15

就我而言,这种情况发生在存储在 Web 项目内的 App_Data 文件夹中的 SQL LocalDB 中。每当我尝试使用包控制台运行 update-database 来使用迁移初始化我的实体框架数据库时,什么也没有发生。然后过了一会儿,我得到了这个错误。

我通过修改 App_Data 上的文件权限解决了这个问题。一旦修好,瞧,它就起作用了。

In my case, this was happening with SQL LocalDB stored in App_Data folder inside Web project. Whenever I try to use Package Console to run update-database to init my Entity Framework database using migrations, nothing happens. Then after a while, I get that error.

I solved this by revising file permissions on App_Data. Once fixed, voila, it worked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文