Zdalny sponsor przestaje być wywoływany
Mam aplikację, która tworzy kilka domen aplikacji w jednym procesie i komunikuje się między nimi poprzez zdalne przesyłanie. Tworzę sponsorów dla wszystkich obiektów, aby nie dopuścić ich do GCed.
Ale i tak niektórzy skończyli jako GCed. Po pewnym dochodzeniu ustaliłem, że w zależności odInitialLeaseTime
ustawieni na moich odległych obiektach, moi sponsorzy nigdy nie dzwonią ani nie są wywoływani kilka razy i nigdy więcej.
Mój sponsor (Usunąłem sprawdzanie poprawności pod kątem zwięzłości):
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;
}
}
}
Mój przypadek testowy:
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;
}
}
Jeśli wyjdęInitialLeaseTime
w 5 minut, domyślnie .NET, mój sponsor nigdy nie zostanie wywołany. Jeśli ustawię go na 2 minuty, zostanie wywołany dwa razy, a następnie nigdy więcej. Jeśli ustawię ją na 1 minutę, będzie ona wywoływana w sposób ciągły i będzie działać zgodnie z oczekiwaniami, że wartości domyślne będą działać.
Aktualizacja
Od tego czasu ustaliłem, żeILease
obiekty moich sponsorów są GCed. Zaczynają od domyślnego 5-minutowego czasu dzierżawy, co wyjaśnia, jak często dzwoni moich sponsorów. Kiedy ustawię mojeInitialLeaseTime
do 1 minILease
przedmioty są ciągle odnawiane z powodu ichRenewOnCallTime
domyślnie 2min.
Co ja robię źle? Nie widzę sposobu na tworzenie sponsorów dla obiektów dzierżawy moich sponsorów.