远程发起人停止被调用 [英] Remoting sponsor stops being called

查看:22
本文介绍了远程发起人停止被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,它在单个进程中创建多个 AppDomains,并通过远程处理在它们之间进行通信.我为所有对象创建了赞助商,以防止它们被 GC.

I've got an app which creates several AppDomains in a single process and communicates between them via remoting. I create sponsors for all objects to prevent them from being GCed.

但是,无论如何,有些最终还是被垃圾回收了.经过一些调查,我确定根据我的远程对象上设置的 InitialLeaseTime,我的赞助商要么从未被调用过,要么被调用了几次,然后再也没有.

But, some ended up being GCed anyway. After some investigation I've determined that depending on the InitialLeaseTime set on my remote objects, my sponsors are either never called or get called a couple times and then never again.

我的赞助商(为了简洁起见,我删除了一些完整性检查):

My sponsor (I've removed some sanity checking for brevity):

class Sponsor : MarshalByRefObject, ISponsor, IDisposable
{
    ILease lease;

    public Sponsor(MarshalByRefObject mbro)
    {
        lease = (ILease)RemotingServices.GetLifetimeService(mbro);
        lease.Register(this);
    }

    public TimeSpan Renewal(ILease lease)
    {
        return this.lease != null ? lease.InitialLeaseTime : TimeSpan.Zero;
    }

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

我的测试用例:

class Program : MarshalByRefObject
{
    static void Main(string[] args)
    {
        AppDomain ad = AppDomain.CreateDomain("Remote");

        Program obj = (Program)ad.CreateInstanceAndUnwrap(
            typeof(Program).Assembly.FullName,
            typeof(Program).FullName);

        using (new Sponsor(obj))
        {
            // sleep for 6 minutes.
            // 5 seems to be the point where it gets GCed.
            Thread.Sleep(6 * 60 * 1000); 

            // throws a RemotingException
            obj.Ping();
        }
    }

    void Ping()
    {
    }

    public override object InitializeLifetimeService()
    {
        ILease lease = (ILease)base.InitializeLifetimeService();

        if (lease.CurrentState == LeaseState.Initial)
        {
            // this is the .NET default. if used, the lease is never renewed.
            //lease.InitialLeaseTime = TimeSpan.FromMinutes(5);

            // if uncommented, lease is renewed twice and never again.
            //lease.InitialLeaseTime = TimeSpan.FromMinutes(2);

            // if uncommented, lease is renewed continually.
            //lease.InitialLeaseTime = TimeSpan.FromMinutes(1);
        }

        return lease;
    }
}

如果我将 InitialLeaseTime 保留为 5 分钟(.NET 默认值),我的赞助商将永远不会被调用.如果我将它设置为 2 分钟,它将被调用两次,然后再也不会调用.如果我将它设置为 1 分钟,它将被不断调用并按照我期望的默认值工作.

If I leave the InitialLeaseTime at 5 minutes, the .NET default, my sponsor will never be called. If I set it to 2 minutes, it will be called twice and then never again. If I set it to 1 minute, it will be called continually and work how I expected the default values to work.

更新

我已经确定我的赞助商自己的 ILease 对象正在被垃圾回收.他们从默认的 5 分钟租用时间开始,这解释了我的赞助商被调用的频率.当我将 InitialLeaseTime 设置为 1 分钟时,ILease 对象会不断更新,因为它们的 RenewOnCallTime 是 2 分钟的默认值.

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.

我做错了什么?我看不到为我的赞助商的租赁对象创建赞助商的方法.

What am I doing wrong? I don't see a way to create sponsors for the lease objects of my sponsors.

推荐答案

问这个问题已经很久了,但我今天遇到了这个问题,几个小时后,我想通了.5 分钟问题是因为必须从 MarshalByRefObject 继承的赞助商也有关联的租约.它是在您的客户端域中创建的,并且您的主机域有一个代理到您的客户端域中的引用.除非您覆盖 Sponsor 类中的 InitializeLifetimeService() 方法或该赞助商有自己的赞助商防止其过期,否则这将在默认 5 分钟后到期.

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.

有趣的是,我通过在赞助商的 InitializeLifetimeService() 覆盖中返回 Null 以赋予它无限的时间跨度租期来克服这个问题,并且我创建了我的 ISponsor 实现以在主机 MBRO 中删除它.

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.

这篇关于远程发起人停止被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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