【问题标题】:Proper implementation of IDisposable to clean up Rx Observers w/ long-lived Observables?正确实施 IDisposable 以清理带有长期可观察对象的 Rx 观察者?
【发布时间】:2012-08-22 16:25:21
【问题描述】:

我正在使用 IDisposableCompositeDisposable 来清理我的 ViewModel 中的反应式扩展 (Rx) 观察者。

在这种情况下,我的 ViewModel 中 IDisposable 的正确实现是什么?通常,我不会实现终结器,因为没有非托管对象,但似乎终结器可能有助于捕获对Dispose 的任何未接来电,从而确保始终处置我的观察者。 (我的 Observable 在应用程序的整个生命周期内都会被实例化,而 ViewModel 则不会。)

谢谢!

更新:

一些澄清:在这种情况下,调用 Dispose 的需求略有不同。 Reactive Extensions 中的 Observer 使用 Dispose 取消订阅 Observable。就我而言,我有一个长期存在的观察者和许多短期观察者,因此观察者不会是 GC,除非由于 Observable->Observer 引用而显式处置。我对 Reactive Extensions 完全陌生,所以我的理解可能有误。

【问题讨论】:

  • 这样的终结者还能做什么?
  • 只需调用 Dispose(),从而确保 Observers 已从 Observable 中取消订阅。
  • 如果需要清理观察者,那么他们是否不想拥有终结者而不是容器?

标签: c# .net mvvm system.reactive idisposable


【解决方案1】:

您不应该使用终结器在其他托管对象上调用 Dispose()(或任何方法)。这些对象可能已经完成(因为无法保证完成的顺序:http://msdn.microsoft.com/en-us/library/system.object.finalize(v=vs.100).aspx

由于这些对象本身是 IDisposable,因此它们的终结器(如果有的话)将负责在未调用 Dispose() 时需要完成的任何工作(假设它们已正确实现)。

【讨论】:

  • 情况比我理解的要复杂一些。 A 持有对 B 的引用,B 持有对 C 的引用,C 持有对 B 的引用。处置 A 将调用 B 的方法,该方法告诉 C 释放其对 B 的引用。忘记处置 A 意味着 B 将只要 C 不能,就永远不要收集垃圾。
  • 多次调用Dispose() 应该是安全的。最好叫它一次,总比不叫。
  • 确实,问题已经问过这个问题:“但似乎终结器可能有助于捕获任何未接来电的 Dispose”。也许拥有一个只用于调试的终结器 Debug.Assert(disposed); 会是一个很好的折衷方案?
  • 如果包含对象的终结器没有解决问题,那么包含对象的终结器就很难解决。添加终结器以捕获它应该在调试模式下调用是一回事,而只是减慢终结器的速度。
  • @HenkHolterman,我现在明白你的意思了。谢谢。我以为您在争辩说错过对 Dispose() 的调用永远不会放弃资源-但您只是说错过调用会增加放弃资源的延迟,并且在此期间程序可能会失败。好点。
【解决方案2】:

您不需要 Dispose Rx IDisposables,除非您明确希望比正常情况提前退订。只是泄漏它们。它们不代表非托管内存,因此 CLR 将像任何其他对象一样对它们进行 GC。并且永远不要在这些对象上实现终结器。

您也不必担心引用循环,CLR 的 GC 足够聪明,可以检测到它们(就像您有 someA.B = someB; and someB.A = someA 一样)

【讨论】:

  • 我知道我可以忽略对“Observer.Dispose”的调用是观察者和观察者有相似的生命周期,但是在我的场景中,观察者在应用程序的生命周期中持续存在,观察者是经常创建和销毁。在这种情况下,Observable 不会持有对 Orphaned Observer 的引用,从而阻止垃圾收集吗? (我觉得我在某个地方读到过这个)。
【解决方案3】:

您不应使用终结器调用 Dispose() 来取消订阅 Rx 订阅。终结器仅在对象即将被垃圾收集时被调用,垃圾收集仅在对象不再能够被引用时发生。如果有当前订阅,那么它有引用并且不会被垃圾回收。

您必须亲自致电.Dispose() - 明确地 - 以便清理您的订阅。

【讨论】:

    猜你喜欢
    • 2011-06-17
    • 2016-08-26
    • 2012-01-19
    • 1970-01-01
    • 2019-01-30
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多