Nig*_*elP 9 .net memory-leaks uwp windows-10-universal
所以我在最新版本的Windows 10上使用VS2017 v15.6.4开始使用UWP并在C#中开发一个简单的应用程序.
运行应用程序时,我注意到它的内存使用量会持续增加.
经过大量的代码配对后,我得出的结论是,这是由页面导航调用引起的,例如:
Frame.Navigate(typeof SomePage);
Frame.GoBack();
Frame.GoForward();
Run Code Online (Sandbox Code Playgroud)
创建和观察这个过程非常容易......
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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
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 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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以看到这个简单的测试应用程序包含2个页面,当它运行时,应用程序将以每秒100次(通过计时器)的速率自动在两个页面之间导航,直到您关闭应用程序.
5)构建并运行应用程序.还要运行任务管理器并记下应用程序的初始内存占用量.
6)去喝杯咖啡.当你回来时,你会看到内存使用量增长了.它将继续增长.
现在我知道这个例子是不现实的,但它纯粹是为了证明我怀疑是影响大多数(如果不是全部)UWP应用的基本问题.
试试这个...
运行Windows 10设置应用程序(由Microsoft开发的UWP应用程序).再次,请注意它在任务管理器中的初始内存占用量.(在我的工具包上,这个起始大约12.1 MB).
然后反复单击系统设置图标...然后按返回按钮...然后系统设置图标...然后返回按钮...你明白了.并且观察内存占用也会增加.
几分钟后,我的MS设置应用程序内存消耗增加到超过90 MB.
此内存消耗似乎与UWP页面复杂性有关,如果您开始向页面添加大量XAML控件(尤其是图像控件),它会迅速上升.不久我的功能丰富的UWP应用程序消耗1-2GB内存.
所以这个"问题"似乎会影响所有基于框架的UWP应用程序.我已经在3台不同的PC上尝试了其他UWP应用程序,我看到了同样的问题.
使用我的功能丰富的应用程序,内存消耗已经非常糟糕,我现在正在考虑完全取消页面导航并将所有内容放在MainPage上.这不是一个愉快的想法.
无效的潜在解决方案......
我遇到过其他描述类似问题的文章,并且提出了我尝试过的解决方案,这些解决方案没有任何区别......
1)将以下任一行添加到.xaml页面定义中没有帮助...
NavigationCacheMode="Required"
NavigationCacheMode="Enabled"
Run Code Online (Sandbox Code Playgroud)
2)切换页面时手动强制垃圾收集没有帮助.所以做这样的事情没有任何区别......
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
GC.Collect();
}
Run Code Online (Sandbox Code Playgroud)
有谁知道是否有解决方案,或者它是UWP应用程序的基本问题?
在提供的repro代码中,您继续前进,这将创建页面实例的无限导航后退堆栈(请检查Frame.BackStack.Count)。由于这些实例存储在内存中,因此应用程序的内存使用量自然会不受限制地增长。
如果更改代码以导航回MainPage,因此将后退堆栈深度保持为2,则反复进行来回导航不会明显增加内存。
编辑 但是,如果我们在更长的时间内观察到这一点,则内存的增加是可测量的(在我的测试中,每个导航1.5KB)。自Windows 10 Update 1803起,这是平台代码中的已知漏洞尚未解决。
您在此处共享测试项目的更新版本:
这是NewPage.cs的代码:https ://1drv.ms/u/s!AovTwKUMywTNoYVFL7LzamkzwfuRfg
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();
long managedMem = GC.GetTotalMemory(true);
ulong totalMem = Windows.System.MemoryManager.AppMemoryUsage;
System.Diagnostics.Debug.WriteLine(string.Format("Managed Memory: {0} / Total Memory: {1}", managedMem, totalMem));
}
private void Timer_Tick(object sender, object e)
{
timer.Stop();
Frame.GoBack();
}
}
Run Code Online (Sandbox Code Playgroud)
如果在真正的应用程序中,您仅在几个导航周期后就观察到MB大小的泄漏,则这不是由于上述平台错误,而是由于需要在特定应用程序中使用VS内存分析器进行其他调查例。通常,应用程序代码中的循环引用或静态事件处理程序可能导致泄漏。调试这些错误的一个很好的第一步是查看强制GC时页面的终结器是否按预期命中。如果不是,请使用VS内存分析工具来确定哪些对象正在泄漏以及谁在坚持。这些数据将有助于在特定情况下在应用代码中查明根本原因。通常,这是由于循环引用或未取消订阅静态事件处理程序造成的。如果您可以通过分析实际应用程序共享信息,很乐意为您提供更多帮助。