2013-09-08 4 views
1

저는 하나의 프로세스에서 여러 AppDomains를 생성하고 원격을 통해 이들간에 통신하는 앱을 가지고 있습니다. 나는 모든 객체에 대해 스폰서를 만들어 GCed가되지 않도록합니다.원격 스폰서가 호출되지 않습니다.

그러나 일부는 GCed로 처리됩니다. 조사가 끝난 후 원격 객체에 설정된 InitialLeaseTime에 따라 스폰서가 호출되지 않았거나 몇 번 호출 된 다음 다시는 호출되지 않습니다. 나는 InitialLeaseTime을 5 분의두면

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

:

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

내 테스트 케이스 :

내 스폰서는 (나는 간결 확인 약간의 정신을 삭제했습니다) .NET 기본값. 스폰서는 절대 호출되지 않습니다. 2 분으로 설정하면 두 번 호출되고 다시는 호출되지 않습니다. 1 분으로 설정하면, 지속적으로 호출되고 기본값이 어떻게 작동하는지 예상합니다.

업데이트

내가 결정 이후로했습니다 내 스폰서의 ILease 객체 자체가 GCed되는 것을. 기본 5 분 임대 시간부터 시작하여 스폰서가 얼마나 자주 전화를 받는지 설명합니다. InitialLeaseTime을 1 분으로 설정하면 ILease 개체는 RenewOnCallTime이 기본값 인 2 분이므로 지속적으로 갱신됩니다.

내가 뭘 잘못하고 있니? 스폰서의리스 오브젝트에 대한 스폰서를 만드는 방법이 없습니다.

+0

귀하의 테스트 값은 사용 된 스폰서가 클라이언트 객체이고 또한 (기본값으로) 만료되었으므로 스폰서 목록에서 삭제되었으며 임대를 갱신하지 않았 음을 나타냅니다. –

+0

그 이유는'System.Runtime.Remoting.Lifetime.ClientSponsor. InitializeLifetimeService'가 null을 반환합니다. –

답변

1

나는 매우 비슷한 문제와 대답 "Sponsor's Renewal function stops being called"를 게시했습니다. 심지어 같은 문제 일 수도 있습니다.

전 스폰서를 클라이언트 대신 서버에 배치하여 해결했습니다. 서버 측 스폰서는 원격 객체를 안전하게 유지할만큼 안정적으로 호출되는 것 같습니다. 클라이언트가리스 만료 대신 스폰서를 적극적으로 연결 해제해야하기 때문에이 방법은 많은 경우에있어 매우 안전한 해결책은 아님을 알고 있습니다.

+0

현재 내 해결 방법은 자체 임대를 관리하는 것입니다. 슬프게도 제대로 사용하는 방법에 대한 Microsoft의 지침이없는 것 같습니다. –

1

이 질문 이후로 오랜 시간이 걸렸지 만 오늘이 문제에 부딪 혔고 몇 시간 후, 나는 그것을 알아 냈습니다. 5 분 문제는 MarshalByRefObject에서 상속해야하는 스폰서에도 연결된리스가 있기 때문입니다. 그것은 귀하의 클라이언트 도메인에서 생성되고 귀하의 호스트 도메인은 귀하의 클라이언트 도메인에있는 참조에 대한 프록시를 갖습니다. 이 옵션은 스폰서 클래스의 InitializeLifetimeService() 메소드를 재정의하거나 스폰서가 만료되지 않도록 자체 후원자가없는 경우 기본 5 분 후에 만료됩니다.

Funnily 충분히 스폰서의 InitializeLifetimeService() 재정의 Null을 반환하여 무한 타임스리스를 제공하고 호스트 MBRO에서이를 제거하는 ISponsor 구현을 만들었습니다.