2

1 つのプロセスで複数の AppDomains を作成し、リモート処理を介してそれらの間で通信するアプリがあります。すべてのオブジェクトのスポンサーを作成して、それらが GC されないようにします。

しかし、とにかくGCされたものもあります。いくつかの調査の結果InitialLeaseTime、リモート オブジェクトのセットによっては、スポンサーが呼び出されないか、数回呼び出されてから二度と呼び出されないことがわかりました。

私のスポンサー(簡潔にするためにいくつかの健全性チェックを削除しました):

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

.NET のデフォルトである 5 分で退出するInitialLeaseTimeと、スポンサーは呼び出されません。2 分に設定すると、2 回呼び出され、その後は呼び出されません。1分に設定すると、継続的に呼び出され、デフォルト値が期待どおりに機能します。

アップデート

それ以来ILease、私のスポンサー自身のオブジェクトが GC されていると判断しました。彼らはデフォルトの 5 分のリース時間から始めます。これは私のスポンサーが呼び出される頻度を説明しています。1 分に設定すると、デフォルトが 2 分であるためInitialLeaseTimeILeaseオブジェクトは継続的に更新されます。RenewOnCallTime

私は何を間違っていますか?スポンサーのリース オブジェクトのスポンサーを作成する方法がわかりません。

4

2 に答える 2

1

私は非常によく似た問題を投稿し、「スポンサーの更新機能が呼び出されなくなりました」と回答しました。それも同じ問題かもしれません。

クライアントではなくサーバーにスポンサーを配置することで、この問題を回避しました。サーバー側のスポンサーは、リモート オブジェクトを存続させるのに十分なほど確実に呼び出されているようです。多くの場合、これは非常に安全な解決策ではないことはわかっています。これは、クライアントが単にリースを期限切れにするのではなく、積極的にスポンサーを切断する必要があるためです。

于 2013-09-23T01:38:17.100 に答える