.net 导航页面时是否所有UWP应用都会泄漏内存?
因此,我一直致力于UWP,并在最新版本的Windows 10上使用VS2017 v15.6.4在C#中开发了一个简单的应用程序 在运行应用程序时,我注意到它的内存使用量随着时间的推移不断增加 经过大量代码配对,我得出结论,这是由页面导航调用引起的,例如:.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)项目,称之
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程序开发托管代码,在这些程序中,不断增加的内存