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 分であるためInitialLeaseTime
、ILease
オブジェクトは継続的に更新されます。RenewOnCallTime
私は何を間違っていますか?スポンサーのリース オブジェクトのスポンサーを作成する方法がわかりません。