在使用.NET的Reactive Extensions时保持对"IDisposable"的引用:总是,从不,或者有时候?

Eni*_*ity 16 .net garbage-collection idisposable system.reactive

到现在为止,我还热心地保持每个参考IDisposable任何返回.Subscribe(...),.Connect(...)在RX等,方法.我之所以这样做,是因为我担心如果我不保留参考,垃圾收集将丢弃一次性物品.

但是,我做了一个测试在LINQPad在那里我做了一些电话GC.Collect().Subscribe(...),我没有保持基准和猜测什么?世界没有结束,订阅也完成了.

在进一步测试中,我发现我的订阅在.OnComplete()没有我干预的情况下立即被处理掉.

这使我理解,至少对于.Subscribe(...),保持对订阅的引用的唯一原因是强制订阅在其正常完成之前结束.它更像是取消令牌.

所有Rx一次性用品都用于取消而不是保持活力吗?

那么,什么是挂在上面的规则IDisposable

小智 18

除非您希望将来取消订阅可观察的来源,否则无需保留IDisposable对象.类似于IScheduler上的Schedule方法,其返回的IDisposable对象可用于取消计划的操作.

垃圾收集器不直接关注IDisposable对象,也不在任何对象上实现终结器,所以基本上订阅的生命周期管理等完全取决于你在Rx的世界.如果你愿意,可以将它与Win32句柄进行比较,Dispose相当于CloseHandle.

琐事:在设计Rx期间的某个时刻,可取消操作返回一个Action,其调用将导致取消.在自然界中具有相当的功能灵感,但对某些人来说不太明显.因此,我们决定采用已经代表资源管理概念的界面,IDisposable是明显的选择.这就是说,它与.NET Framework中其他地方的接口的典型用法略有不同:

  • 您通常只会将IDisposable对象放在地板上,特别是对于您从未取消订阅的无限序列.
  • 在大多数情况下,由于框架固有的异步特性,您不会对Rx IDisposable对象使用using语句.

希望这可以帮助,

-Bart(Rx团队)


Ric*_*lay 8

IDisposable由归国IScheduler.Schedule(),如果你想取消计划的行动是唯一有用的(也就是之前发生了什么错误)

IDisposable由归国IObservable.SubscribeIConnectableObservable.Connect相等,在处置或者将终止订阅源观测.

至于垃圾收集,虽然Rx使得它更难以衡量,但它仍然受GC规则的约束.如果您的observable的源是root(如UI控件的事件),那么您不必担心它是GC'd.

如果你的源是一个Observable.Interval或其他东西基本上是一个递归IScheduler调用,那么调度程序应该保持它活着(即线程池,任务池或调度程序),因为observable根植于调度程序(via IScheduler.Schedule).