Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 导航页面时是否所有UWP应用都会泄漏内存?_.net_Uwp_Memory Leaks_Windows 10_Windows 10 Universal - Fatal编程技术网

.net 导航页面时是否所有UWP应用都会泄漏内存?

.net 导航页面时是否所有UWP应用都会泄漏内存?,.net,uwp,memory-leaks,windows-10,windows-10-universal,.net,Uwp,Memory Leaks,Windows 10,Windows 10 Universal,因此,我一直致力于UWP,并在最新版本的Windows 10上使用VS2017 v15.6.4在C#中开发了一个简单的应用程序 在运行应用程序时,我注意到它的内存使用量随着时间的推移不断增加 经过大量代码配对,我得出结论,这是由页面导航调用引起的,例如: Frame.Navigate(typeof SomePage); Frame.GoBack(); Frame.GoForward(); 创建和观察此过程非常容易 1) 在VS2017中,创建一个新的空白应用程序(通用Windows)项目,称之

因此,我一直致力于UWP,并在最新版本的Windows 10上使用VS2017 v15.6.4在C#中开发了一个简单的应用程序

在运行应用程序时,我注意到它的内存使用量随着时间的推移不断增加

经过大量代码配对,我得出结论,这是由页面导航调用引起的,例如:

Frame.Navigate(typeof SomePage);
Frame.GoBack();
Frame.GoForward();
创建和观察此过程非常容易

1) 在VS2017中,创建一个新的空白应用程序(通用Windows)项目,称之为PageTest

2) 将新空白页添加到项目中,并将其命名为“NewPage”

3) 将以下代码添加到MainPage.xaml.cs:

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace PageTest
{
    public sealed partial class MainPage : Page
    {
        DispatcherTimer timer = new DispatcherTimer();

        public MainPage()
        {
            InitializeComponent();
            timer.Interval = TimeSpan.FromSeconds(.01);
            timer.Tick += Timer_Tick;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            timer.Start();
        }

        private void Timer_Tick(object sender, object e)
        {
            timer.Stop();
            Frame.Navigate(typeof(NewPage));
        }
    }
}
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace PageTest
{
    public sealed partial class NewPage : Page
    {
        DispatcherTimer timer = new DispatcherTimer();

        public NewPage()
        {
            InitializeComponent();
            timer.Interval = TimeSpan.FromSeconds(.01);
            timer.Tick += Timer_Tick;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            timer.Start();
        }

        private void Timer_Tick(object sender, object e)
        {
            timer.Stop();
            Frame.Navigate(typeof(MainPage));
        }
    }
}
4) 将以下(几乎相同)代码添加到NewPage.xaml.cs:

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace PageTest
{
    public sealed partial class MainPage : Page
    {
        DispatcherTimer timer = new DispatcherTimer();

        public MainPage()
        {
            InitializeComponent();
            timer.Interval = TimeSpan.FromSeconds(.01);
            timer.Tick += Timer_Tick;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            timer.Start();
        }

        private void Timer_Tick(object sender, object e)
        {
            timer.Stop();
            Frame.Navigate(typeof(NewPage));
        }
    }
}
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace PageTest
{
    public sealed partial class NewPage : Page
    {
        DispatcherTimer timer = new DispatcherTimer();

        public NewPage()
        {
            InitializeComponent();
            timer.Interval = TimeSpan.FromSeconds(.01);
            timer.Tick += Timer_Tick;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            timer.Start();
        }

        private void Timer_Tick(object sender, object e)
        {
            timer.Stop();
            Frame.Navigate(typeof(MainPage));
        }
    }
}
您可以看到,这个简单的测试应用程序包含2个页面,当它运行时,该应用程序将以每秒100次的速度(通过计时器)在这两个页面之间自动导航,直到您关闭该应用程序

5) 构建并运行应用程序。同时运行任务管理器并记录应用程序的初始内存占用

6) 去冲杯咖啡。当你回来的时候,你会看到内存使用量增加了。它将继续增长

现在我知道这个例子是不切实际的,但这里纯粹是为了证明我怀疑的是影响大多数(如果不是所有)UWP应用程序的根本问题

试试这个

运行Windows 10设置应用程序(由Microsoft开发的UWP应用程序)。同样,请注意任务管理器中的初始内存占用。(在我的套件中,这大约从12.1MB开始)

然后反复单击系统设置图标。。。然后按下后退按钮。。。然后系统设置图标。。。然后按下后退按钮。。。你明白了。并且观察内存占用也会增加

这样做几分钟后,我的MS设置应用程序的内存消耗增加到90 MB以上

这种内存消耗似乎与UWP页面复杂性有关,如果开始向页面添加大量XAML控件,尤其是图像控件,内存消耗会迅速增加。不久我的功能丰富的UWP应用程序就会消耗1-2GB内存

所以这个“问题”似乎影响了所有基于帧的UWP应用程序。我在3台不同的电脑上尝试过其他UWP应用程序,我发现它们都有同样的问题

有了我的功能丰富的应用程序,内存消耗变得非常糟糕,我现在正考虑完全取消页面导航,将所有内容都放在主页上。这不是一个愉快的想法

不起作用的潜在解决方案…

我曾遇到过其他描述类似问题的文章,我也尝试过一些建议的解决方案,但没有任何区别

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    GC.Collect();
}
1) 将以下任一行添加到.xaml页面定义中都没有帮助

NavigationCacheMode="Required" 

NavigationCacheMode="Enabled" 
2) 切换页面时手动强制垃圾收集没有帮助。所以这样做没什么区别

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    GC.Collect();
}

有人知道是否有解决方案,或者这是UWP应用程序的基本问题吗?

在复制代码中,如果您继续向前导航,将创建页面实例的无限导航backbackback(检查Frame.backstack.Count)。由于这些实例存储在内存中,应用程序的内存使用量自然会增加

如果将代码更改为导航回主页面,并因此将backbackback depth保持为2,则重复来回导航时内存不会明显增加

编辑 然而,如果我们在较长时间内观察到这一点,则内存会显著增加(在我的测试中,每次导航1.5KB)。这是一个已知的平台代码泄漏,截至Windows 10 Update 1803,尚未解决

您的测试项目的更新版本在此处共享:

以下是NewPage.cs的代码:


如果在实际应用程序中,您在几个导航周期后观察到MB大小的泄漏,那么这不是由于上述平台错误,而是由于需要在特定应用程序中进行调查的其他原因,例如VS memory profiler。通常,由于应用程序代码中的循环引用或静态事件处理程序,可能会导致泄漏。调试这些功能的第一步是查看强制GC时页面的终结器是否按预期命中。如果没有,请使用VS内存分析工具来确定哪些对象正在泄漏,以及谁在继续泄漏。这些数据将有助于在特定案例的应用程序代码中查明根本原因。通常,这是由于循环引用或静态事件处理程序未被取消订阅。如果您可以共享分析实际应用程序的信息,很高兴能在这方面提供更多帮助。

是。这是UWP中的一个bug。几个月前我打开了一张微软的支持票,他们上周说他们发现了漏洞并解决了。他们将在下一次更新中随windows insider预览版一起发布修复程序(因此我认为下周——2018年12月21日,它仍然没有包括在内)。适用于所有人的修复程序将随windows 10的春季更新一起提供。

我们在针对>=RS3(Win 10 1709)的最新UWP 6.2.9 Nuget更新中,在内存处理和GC调用方面做了巨大改进。完整的发行说明是

我在导航时也经历过类似的行为。但它始终处于调试模式。在调试模式下,我的应用程序在导航时甚至超过了100Mb(导航前为40Mb)。但在最终发布的产品中从未超过1Mb。

您真的能让它抛出内存不足异常吗?因为“占用”内存是一个.NET特性,这仅仅是因为垃圾收集器很懒惰,如果没有其他人需要它,它就不需要“释放”任何东西。毕竟,你的RAM是“用过”还是“免费”只在你想用它做其他事情的时候才重要。这是公平的。我查一下。也许值得一提的是,多年来我一直在为WinForms/WPF程序开发托管代码,在这些程序中,不断增加的内存