2014-01-06 1 views
1

이것은 잠재적으로 매우 어리석은 질문이지만 Linq 확장 메서드로 생성 된 IObservables를 유지해야하는지 잘 모르겠습니다. 대부분의 예제는 기본적으로 그렇게 보이지만 장시간 실행되는 프로그램에서는 어떻게 될 것입니다. 내 질문을 설명하는 두 가지 예제가 있습니다 :'Linqed'의 수명 반향 식을 사용하여 IObservable

내 첫 번째, 현재 기본 구현은 pub \ sub 이벤트 수집기에서 제공하는 IObservable 구독을 포함합니다. 관측기가 집계자가있는 한 주위에있을 것이라는 것을 알고 있기 때문에 나는 이것에 익숙하다.

IDisposable altSendSubscription = Events.GetStream<OutgoingByteMessage>() 
    .Where(msg => msg.Identifier.ChannelId == this.Id) 
    .Select(msg => Tuple.Create(msg.Identifier.ConnectionId, msg.Data)) 
    .Subscribe(item => 
    {      
     _sendQueue.Enqueue(item);      
    }); 

내 질문은, 그 두 번째 버전에, 나는 유지해야한다 : 그 논리의 일부를 분해 Linq를 사용하는 경우

protected virtual void SubscribeToEvents() 
{ 
    _subscriptions.Dispose(); 
    _subscriptions = new CompositeDisposable(); 

    IDisposable sendSubscription = Events.GetStream<OutgoingByteMessage>() 
     .Subscribe(msg => 
     { 
      if (msg.Identifier.ChannelId == this.Id) 
      { 
       var queueItem = Tuple.Create(msg.Identifier.ConnectionId, msg.Data); 
       _sendQueue.Enqueue(queueItem); 
      } 
     });    

    _subscriptions.Add(sendSubscription);      
} 

그러나, 나는 가입을 얻기 위해이 작업을 수행 할 수 있습니다 저것의 제품. 선택 방법? 이것은 afterall에서 일어나는 일입니다. 기술적으로 IObservable은 SubscribeToEvents가 완료되고 가비지 수집을받을 수있게되면 즉시 범위를 벗어납니다. 또는 IDisposable 개체 자체에 대한 참조를 유지하므로 특정 참조를 어딘가에 보관하지 않아도 안전합니다.

Rx 소스를 살펴본 후 Linq 마법을 달성하기 위해 일련의 전달자 클래스를 사용하는 것처럼 보입니다. 그러나 나는 아직도 약간 편집증을 앓고 있습니다. 너희들은 어떻게 생각하니?

답변

3

하루가 끝날 때 모든 IObservable 개체는 Events.GetStream (물론 구현에 따라 Events.GetStream에 따라) 가입자 목록을 통해 보관됩니다. 이것이 범위를 벗어나는 지 여부는 구현에 따라 다릅니다.

그러나 IDisposable을 보유하면 범위가 계속 유지되므로 구현이 return Observable.Never<OutgoingByteMessage> 인 경우에도 IDisposable 때문에 여전히 존재합니다.

일반적으로 범위를 벗어나는 활성 구독에 대해 걱정할 필요가 없습니다. 구독 누수가 걱정됩니다. 이러한 현상은 사용자가 글로벌 개체 (IoC 컨테이너에서 반환 된 것과 같은)을 구독 할 때 발생하며 구독을 끊지 않습니다 (Observable이 절대로 종료되지 않는 경우).

자주 발생하지 않는 것처럼 들리지만, 예상보다 더 많이 발생합니다. 예를 들면 : 나는 모든 시간을 작성되는 일부 객체의 생성자에서, 내가 청소 만나지 구독 수십 만드는 것이 넣으면

MessageBus.Current.Listen<FooMessage>() 
    .Where(x => x.Bar == "Baz") 
    .Subscribe(x => Console.WriteLine(x)); 

.

2

아니요, 걱정할 필요가 없습니다. 이것을 생각해보십시오 : 사건의 원천이있는 한 관찰 할 수있는 사슬은 구독하는 행위가 모두 연결되기 때문에 수집 할 수 없습니다. 즉, 각 연산자는 부모 참조 인 옵저버를 생성하는 위의 연산자에 가입합니다.

가입 핸들 (altSendSubscription)을 붙잡을 필요조차 없습니다.

왜 메모리 프로파일 러를 사용하고 자신을 납득시키기 위해 힙을 보지 않겠습니까?

관련 문제