2011-05-19 106 views
3

处理在循环中创建的订阅的建议方式是什么? 在下面的人为的例子中,我在for循环中生成订阅,并将它们添加到List,并通过List 来处理它们。这对我来说似乎有点臭,我在想,必须有一个更清洁的方式来清理订阅,除非GC在运行时处理它们。我是否需要明确处理订阅?Rx处置订阅

class Program 
{ 
    static void Main(string[] args) 
    { 
     Func<int, IEnumerable<int>> func = x => 
     { 
      return Enumerable.Range(0, x); 
     }; 

     List<IDisposable> subsriptions = new List<IDisposable>(); 
     for (int i = 1; i < 10; i++) 
     { 
      var observable = func(i).ToObservable().ToList(); 
      var subscription = observable.Subscribe(x => Console.WriteLine(x.Select(y => y.ToString()).Aggregate((s1, s2) => s1 + "," + s2))); 
      subsriptions.Add(subscription); 
     } 
     Console.ReadLine(); 
     subsriptions.ForEach(s => s.Dispose()); 
    } 
} 

回答

13

如果源完成,则不需要处理订阅。在你的例子中,如果你想在完成之前停止枚举Range,你只会处理订阅。

即使在这种情况下,通过使用作为其设计的一部分终止订阅的运营商处理订阅更为常见,如Take,TakeWhile,TakeUntil

如果你想几个IDisposable订阅相结合,CompositeDisposable旨在恰恰如此:

CompositeDisposable subsriptions = new CompositeDisposable(); 

subscriptions.Add(Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe()); 
subscriptions.Add(Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe()); 
subscriptions.Add(Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe()); 

subscriptions.Dispose(); 
+0

@Richard:您能阐述一下“这是比较常见的通过使用终止操作处置订阅订阅作为其设计的一部分“。您是否说,如果“采取元素”的条件评估为false,那么以Where/TakeWhile等谓词为基础的运算符会隐含处置订阅?另外,如果运算符是“选择”而不是基于谓词的过滤器,那么在这种情况下,您是否需要明确处理订阅? – 2011-05-19 18:13:52

+0

你的理解在两个方面都是正确的,但如果你在这个'Select'中增加了一个'Take *',那么这个take就会终止'Select',这会终止源。 – 2011-05-19 19:34:35

+0

非常好。还有一个(不相关的)问题。在我看到的大多数基于控制台应用程序的Rx示例中,通常需要一个console.readline来保持进程的活动状态,直到可观察序列被完全消耗为止(TPL中的任务也是如此)。在API中是否有任何机制来注册调用者可以等待的WaitHandle? – 2011-05-20 01:58:39