UWP Windows 10 应用程序导航时内存增加

31

我有一个UWP Windows 10应用程序,并注意到任务管理器中的内存使用量会随着时间的推移而增加。

我简化了这个应用程序并发现在导航页面时内存会增加。因此,我制作了一个只包含几个页面的简单应用程序进行测试,但是在这个简单的应用程序中内存仍然在增加。我有一个主页面,它会定时从Page1导航到Page2并返回至MainPage。

    public sealed partial class MainPage : Page
{

    private DispatcherTimer _timer;

    private bool _page1Showing;
    private bool _timerRunning;

    public MainPage()
    {
        this.InitializeComponent();

        _timer = new DispatcherTimer();
        _timer.Interval = new TimeSpan(0, 0, 0, 0, 200);
        _timer.Tick += _timer_Tick;
    }

    private void _timer_Tick(object sender, object e)
    {
        GC.Collect();

        this.rootFrame.BackStack.Clear();
        this.rootFrame.ForwardStack.Clear();

        if (_page1Showing)
        {
            this.rootFrame.Navigate(typeof(Page2));
            _page1Showing = false;
        }
        else
        {
            this.rootFrame.Navigate(typeof(Page1));
            _page1Showing = true;
        }
    }


    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (_timerRunning)
        {
            _timer.Stop();
            _timerRunning = false;
        }
        else
        {
            _timer.Start();
            _timerRunning = true;
        }
    }

}

页面1和页面2是空白页面,有背景颜色的网格以便查看导航。当此应用程序运行时,在任务管理器中的内存使用量每30分钟增加约1MB。

我使用VS2015中的内存诊断工具运行了该应用程序,托管堆与预期相同:

enter image description here

堆始终在增加:

enter image description here

比较堆的快照显示:

enter image description here

我不明白这些McgInterop对象是什么?为什么这样一个简单的应用程序内存使用量总是在增加。我的主要应用程序需要长时间运行(几个月或以上)。感谢任何帮助。

我尝试更改页面NavigationCacheMode属性,如果设置为Required,则页面只会创建一次。如果设置为disabled,则页面每次都会创建,并且我检查了期望的终结器被调用。

--

编辑:我添加了一个按钮来启动和停止计时器(已更新上述内容)。似乎当计时器在运行时,任务管理器中的内存使用量会增加,当计时器停止时,内存使用量最终会下降。

我在一天内测量了任务管理器中的内存使用量,每隔约2小时启动和停止计时器,如下所示,它会缓慢增加,然后在某个时刻下降:

12.5 -> 17.1 -> 16.7 -> 13.9 -> 16.8 -> 22.5 -> 13.6 -> 14.6 -> 24.9 -> 15.2

所以我猜一切都正常?但我不清楚这里发生了什么,为什么会增加这么多?在什么条件下会被释放?

系统是否延迟释放内存,而页面正在导航时?当用户通常与屏幕交互时?


4
Frame 保留了导航历史记录。如果偶尔清除后退堆栈,这种情况是否仍会发生? - Kai Brummund
我已经更新了上面的代码以清除后退堆栈,但在任务管理器中内存仍然像以前一样增加。 - tagy22
我写了一个演示(和你的一样),这是内存使用情况图:除了在开始时,内存并没有增加 <br> VS2015更新1。 <br> Windows 10, 10586。 <br> <br> 补充: <br> 我认为你不必每200毫秒调用GC.Collect();,系统会为你调用。我的演示已经运行了将近2个小时,内存并没有持续增加,但有些变化。 <br> 这是关于Visual Studio中Memory Tool的文档链接:http://blogs.msdn.com/b/visualstudioalm/archive/2013/10/16/net-memory-analysis-enhancement - John
1
当您得到一个解决方案时,请在自我回答中分享它。下面的人们(已删除)正在寻求它。谢谢。 - Drew
3个回答

2
每次导航到页面时,都会创建一个新的页面实例,但是上一个页面不会被释放(即使该页面已经在导航堆栈中)。
为了防止多次分配同一页面,请将 NavigationCacheMode 属性设置为 "Enabled"。
此外,为了最小化内存分配,您必须覆盖 OnNavigatedTo 和 OnNavigatedFrom 方法。
在 OnNavigatedTo 方法中:
- 实例化所有内存密集型对象或资源 - 添加所有所需的事件处理程序 - 启动所有计时器、任务或线程
在 OnNavigatedFrom 中:
- 处理所有资源 - 停止所有计时器、任务或线程 - 从所有重量级对象中删除引用 - 删除所有事件处理程序 - 如果确实需要,则调用 GC.Collect()

从我的问题中:我已经尝试更改页面的NavigationCacheMode,如果设置为Required,则页面只会创建一次。如果设置为disabled,则每次都会创建页面。 - tagy22
如果您使用required,您可能会冒着内存不足的风险,启用操作系统缓存仅在可能的情况下缓存页面。 禁用后,操作系统应自动释放实例以释放内存,但根据我的经验,它并不起作用。 此外,如果您使用缓存,您必须在'OnNavigatedFrom'上处理资源,例如,您可以处置计时器而不仅仅停止它。 - Stefano Balzarotti

1

0

我在使用charmBar打印时,在w8.1上遇到了同样的问题,它会消耗大量内存,直到应用程序崩溃(1.5 GB)。但通常情况下,您不需要GC.colect(),它会自动工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接