【问题标题】:Remove Pages windows phone删除 Pages windows phone
【发布时间】:2015-02-08 12:14:28
【问题描述】:

我有一个大项目,我的应用程序一直保留我导航离开的页面。该页面仅使用最少,并且有很多图形,因此我希望将其从内存中完全删除。

因此我使用了以下

 NavigationService.RemoveBackEntry();

使用我看到的分析器,上面的 sn-p 确保我只有 1 个页面实例。但由于它的图形很重,我仍然希望它完全从内存中删除,即分析器中没有实例。

在我的大型应用程序中,我尝试取消订阅所有事件,引入 dispose/finalize 并调用 GC,它有所帮助,但实例仍然存在。

为了排除任何愚蠢的错误,我做了this small sample。仅使用内存弹出检查器在两个哑页面之间导航。但是仍然存在 1-2 个页面实例。是否有强制删除页面以使其没有任何内容存储在内存中的方法?

我已添加:

            while (App.RootFrame.RemoveBackEntry() != null) ;

到 OnNavigated to,它会删除除我开始的第一页之外的所有页面。我使用了调试分析工具包,可以看到无论我从哪个页面开始,当我离开它时,它都不会被删除。

【问题讨论】:

标签: c# silverlight memory navigation windows-phone


【解决方案1】:

WP Silverlight 运行时将在内存中最多保留三个页面,即使从后台堆栈中删除也是如此。我仍然不清楚这种行为的原因,但我找到了一个(丑陋的)解决方法:http://blogs.codes-sources.com/kookiz/archive/2013/11/11/wpdev-give-that-memory-back.aspx

基本上,覆盖页面的OnNavigatedTo 处理程序,并强制垃圾回收三次,通过调用调度程序分开:

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    this.Dispatcher.BeginInvoke(() =>
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();

        this.Dispatcher.BeginInvoke(() =>
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();

            this.Dispatcher.BeginInvoke(() =>
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            });
        });
    });
}

听起来很疯狂,但它确实有效。


在您的情况下,您还有另一个问题。您通过弹出窗口使页面保持活力。让我解释一下:

CreatePopups 方法中,您创建弹出窗口并将其添加到起始页的网格中。 在弹出窗口中,您启动一​​个计时器以定期调用UpdateMemoryInfo。 计时器由 .NET 运行时保持活动状态,直到它停止。计时器会在您的弹出窗口中保留一个引用,因为您使用实例方法作为事件处理程序。您的弹出窗口通过Parent 属性保持对网格的引用。网格通过自己的Parent 属性保持对页面的引用。所以你只是让你的页面不朽,只要你的计时器在滴答作响。 要证明问题存在,只需将 UpdateMemoryInfo 方法设为静态(并删除其中的所有 UI 更新代码)。由于事件处理程序现在是静态的,因此计时器不会保存对弹出实例的引用。运行分析器,您会看到页面实例现在已按预期被垃圾收集器回收。


当然,它假定您的页面已从后台堆栈中删除。通过按返回键或调用NavigationService.GoBack() 方法,或者使用NavigationService.RemoveBackEntry() 手动删除它们(如果您只使用向前导航)

【讨论】:

  • 似乎不起作用,当我们尝试实现它时。即使在问题中包含的虚拟应用程序上。根据您的博客文章,您似乎只能导航出去,然后使用 backkey 返回。但在此应用程序中,不一定使用后键。更有可能的是不同页面之间的导航服务。您是否尝试过仅使用 NavigationService 而不是 backkey。我们实现中的后键用作退出。
  • 我的 cmets 和 JTIM 一样
  • @JonasN89 抱歉,刚刚注意到您的复制项目中还有另一个问题。查看我的编辑。
  • 我猜@JTIM 也是这样
  • @KooKiz 我们错过了UpdateMemoryInfo :/ 但当然正如你所说,它保留了一个参考。但只是一个澄清的评论/问题,因为我们经常使用导航服务而不是返回按钮导航,这个代码 sn-p 'RemoveBackEntry()',仍然应该与您的代码一起使用吗?因为这将确保它不在导航堆栈中被引用,因此可以被收集?其次对于UpdateMemoryInfo,我们如何让它在没有 UI 更新器的情况下更新内存,只需引入一个更新按钮或?今晚我会尝试通过它!感谢您的跟进。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多