0

If I use the ToEnumerable extension on an IObservable, there is a chance the user will not iterate all of the elements. In that case how can the IDisposable declared in Observable.Create be properly disposed?

For the sake of argument let's say that it is not an option to directly return the IObservable to the user (in which case the user could implement cancellation themselves).

 private IObservable<Object> MakeObservable()
 {
   return Observable.Create(async (observer, cancelToken) =>
   {
     using(SomeDisposable somedisposable = new SomeDisposable())
     {
        while(true)
        {
          Object result = somedisposable.GetNextObject();
          if(result == null)
          {
            break;
          }
          observer.OnNext(result);
        }       
     }
   }
 }

 public IEnumerable<Object> GetObjects()
 {
   return MakeObservable().ToEnumerable();
 }

 public void Test()
 {
   IEnumerable<Object> e = GetObjects();
   int i = 0;
   foreach(Object o in e)
   {
     if(i++ == 10)
        break;
   }
   //somedisposable is not disposed here!!!
 }
David S.
  • 5,965
  • 2
  • 40
  • 77

1 Answers1

1

The issue is that your definition of Create doesn't return so it can't be stopped. If you change your source observable to something based on a timer then it works fine. Try this code:

public IEnumerable<long> GetObjects()
{
    return Observable
        .Interval(TimeSpan.FromSeconds(1.0))
        .Finally(() => Console.WriteLine("Done."))
        .ToEnumerable();
}

public void Test()
{
    foreach (long i in GetObjects())
    {
        Console.WriteLine(i);
        if (i == 10)
        {
            break;
        }
    }
}

When you run that you get this output:

0
1
2
3
4
5
6
7
8
9
10
Done.

It's clearly calling OnCompleted on the source observable.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • Thanks. Although I won't use `Interval`, this answer helped me understand why it's happening. I realized I could make more use of the `cancelToken` which also seems to get cancelled upon exiting the foreach. – David S. May 11 '17 at 13:14