最近我注意到我的代码中有一个使用反应扩展的小错误。我订阅了Timer,但从未放弃订阅。这导致内存泄漏。
我创建了突出这种危险的片段:
while (true)
{
Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(1)).Subscribe(Console.WriteLine);
}
这是正常行为吗?
当订阅者与应用程序的其他部分失去连接时,调度程序难道不应该保留对计时器的弱引用,让它被垃圾收集吗?
您可以保留对订阅的引用,甚至可以将它们与CompositeDisposable
组合,但在其他无限运算符(如Timer
)上管理IObservable
生存期的常用方法是使用一个将终止规则应用于另一个运算符的运算符,如Take
(取x值),TakeWhile
(取值,而f(x)
返回true)或TakeUntil
(取值直到另一个序列y发出值或完成为止)。
运行Rx操作符不会自动GC,除非它们已经完成。例如,Timer
/Interval
都使用IScheduler
递归地调度它们的下一个值,并且各种调度器的默认实例都可以通过Scheduler
的静态属性来访问。这使得运行中的运算符始终是根运算符,因此GC不可用。
这是正常的,是的一个功能。
Subscribe()的语义是永远侦听,或者直到Disposed()、OnCompleted()或OnError(),以先到为准。