Search code examples
c#.net-coresystem.reactiverx.net

Dispose after RX subscription


I have a class that contains hot observable. It does some image transformations and collects metrics (int in example for simplicity)

public class Provider
{
  public IObservable<(int Metric, Bitmap Image)> HotObservable { get; }

  public Provider()
  {
    HotObservable = Observable.Interval(TimeSpan.FromSeconds(5))
      .Select(x => ...) // Some processing here
      .Where(x => ...) // Some conditions
      .Publish() // Make it hot
      .RefCount(); // Stay connected while there are subscription
  }

}

I want to expose metrics without images in another observable like that:

public IObservable<int> MetricsObservable { get; } = HotObservable.Select(x => x.Metric);


Problem

Clients can subscribe to either of them but Bitmap should be disposed afterward.

Example client code:

public void SubscribeClient()
{
  MetricsObservable.Subscribe(metric => AccumulateMetrics(metric));
  HotObservable(x => 
  {
    if (x.Image.Width < 1024)
      UploadImage(x.Image);

    // I could dispose image here in this case
  });
}

Worse case:

public void SubscribeClient()
{
  MetricsObservable.Subscribe(metric => AccumulateMetrics(metric));
  // No way to dispose bitmap because it's not here
}

Question: Is it possible in RX to have some kind of handler that fires after all subscriptions are done? Or maybe there is another way to achieve similar behavior?


Solution

  • By their very nature, Observables can be consumed by any client. In your particular case, who decides when and by whom the resource should be disposed? Worst case, one client would dispose the instance before another is allowed to consume it. It seems to me that it isn't the consumer's responsibility to dispose the resource at all. This is true regardless of which observable is subscribed to.

    In my opinion, the originator of the resource owns it, and should take care to dispose it after the value has been emitted.