C# 如果不迭代所有内容,如何处理可观察状态

C# 如果不迭代所有内容,如何处理可观察状态,c#,system.reactive,rx.net,C#,System.reactive,Rx.net,如果我在IObservable上使用ToEnumerable扩展,则用户可能不会迭代所有元素。在这种情况下,如何正确处理Observable.Create中声明的IDisposable 为了便于讨论,我们假设直接将IObservable返回给用户不是一个选项,在这种情况下,用户可以自己实现取消 private IObservable<Object> MakeObservable() { return Observable.Create(async (observer, ca

如果我在IObservable上使用ToEnumerable扩展,则用户可能不会迭代所有元素。在这种情况下,如何正确处理Observable.Create中声明的IDisposable

为了便于讨论,我们假设直接将IObservable返回给用户不是一个选项,在这种情况下,用户可以自己实现取消

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

问题是您的Create定义没有返回,因此无法停止。如果你改变你的源观测到的东西基于定时器,然后它的工作良好。请尝试以下代码:

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;
        }
    }
}
运行时,您将获得以下输出:

0 1 2 3 4 5 6 7 8 9 10 Done. 这显然是在源观测上调用OnCompleted。

谢谢。虽然我不会使用Interval,但这个答案帮助我理解了它发生的原因。我意识到我可以更多地使用cancelToken,它在退出foreach时似乎也会被取消。