【问题标题】:ReactiveUI ObservableAsPropertyHelper / Reactive Extensions Memory Leak?ReactiveUI ObservableAsPropertyHelper / Reactive Extensions 内存泄漏?
【发布时间】:2013-05-16 03:00:43
【问题描述】:

我注意到在使用 ReactiveUI 的 .NET 3.5 应用程序中,我有一个似乎源自 ObservableAsPropertyHelper 的严重内存泄漏。我创建了一个测试项目来演示它here

似乎每个由 ObservableAsPropertyHelper 计算的简单属性触发的更改通知都会泄漏内存。泄漏似乎源自 Reactive Extensions,而不是直接源自 ReactiveUI,但我对 OAPH 的使用非常简单,以至于我想知道是否有人遇到过这个问题或可能有建议的修复。

内存泄漏的严重程度因 .NET 3.5(RxUI 2.4、Rx 1.1)和 .NET 4.0(RxUI 4.2、Rx 2.0.3)而异。 .NET 3.5 中属性的每次更新都更接近线性。但是,.NET 4.0 中仍然存在泄漏。

我已经为我的 .NET 3.5 和 .NET 4.0 测试会话上传了测试项目和一些分析器图像,测试应用程序 here

您可以在图像中看到对象图是不同的,因此我们可能会完全讨论两种不同的泄漏。在 4.0 会话 (40_RetentionGraph.png) 中,您可以看到分配最多的对象是 Ints(我的 OAPH 属性的类型)和 ConcurrentQueue。那里似乎存在某种循环引用问题。您还可以在 40_IntsAllocatedGCRootGrows.png 中看到实例与 GC 根的距离增加了。

在3.5版本(我最关心的)中,可以看到(35_Summary.png)分配最多的对象是Action和ScheduledObserver。对象图比 40 版本稍微复杂一些,完全不同。

我查看了this discussion,但没有找到直接答案:我的情况是,对 OAPH 进行非常简单的更新。对此泄漏的可能解决方案的任何见解表示赞赏。

【问题讨论】:

    标签: .net memory-leaks system.reactive reactiveui


    【解决方案1】:

    您还没有指定调度程序,因此默认情况下 RxUI 会使用 DispatcherScheduler。由于您的应用程序是控制台应用程序,因此没有正在运行的 Dispatcher。所有内存都被 OnNext 的排队所消耗,没有任何东西可以运行它们。

    您可以搞乱启动调度程序并为其提供要运行的帧(WPF 应用程序会为您执行此操作),或者为了测试,只需从这里更改 ReactiveTester 构造函数:

    public ReactiveTester()
    {
      _Total = this.WhenAny(x => x.A, x => x.B, (a, b) => a.Value + b.Value)
                   .ToProperty(this, x => x.Total);
    }
    

    到这里:

    public ReactiveTester()
    {
      _Total = this.WhenAny(x => x.A, x => x.B, (a, b) => a.Value + b.Value)
                   .ToProperty(this, x => x.Total, 0, Scheduler.CurrentThread);
    }
    

    一切都会变得美好。

    【讨论】:

    • 是的,我在提交的 RxUI 错误中怀疑这一点。干得好。
    • 你是对的,添加这个解决了测试应用程序中的问题。谢谢詹姆斯和保罗!我想我的后续问题是:什么可能导致我的 WPF 应用程序中出现类似的泄漏?我的 .WhenAny() 是从 UI 和后台线程调用的。我是否需要在每个 .ToProperty() 调用中明确指定调度程序?如果是,应该是 Scheduler.CurrentThread 吗?
    • 我在没有看到您的代码的情况下进行推测,但我看到您的 3.5 示例正在使用 RxUI 和 Rx 1.1。 IIRC,如果您在非 UI 线程上调用 ToProperty() 并且未指定调度程序,则该组合将导致创建新的 Dispatcher(不会被抽出)。尝试在 Dispatcher 上运行您的初始化代码。
    • 您实际上应该只在 ViewModels 的构造函数中调用 ToProperty,并且您应该只在 UI 线程上创建 ViewModels(尽管第二个并非总是为真,这是一个好主意™,尤其是在这种情况下)
    • “IIRC,这种组合将导致创建一个新的 Dispatcher” - 有趣,不知道。
    猜你喜欢
    • 2014-02-16
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2013-01-20
    • 2011-10-31
    • 2019-08-10
    相关资源
    最近更新 更多