我为 UWP 编写了一个音乐播放器,它在播放音乐时使用一些动画,如旋转封面。
我注意到桌面窗口管理器 (dwm.exe) 每秒消耗大约 1 MB 的内存。上面显示的动画每秒消耗大约 300-400kb。关闭应用程序不会释放内存。
暂停动画将停止韭菜。恢复它,它又开始泄漏。
Animated元素是这样定义的(完整文件在github):
<Ellipse
x:Name="CoverDisc"
Margin="{Binding ElementName=root, Path=ProgressThikness, Converter={StaticResource thiknessConver}, ConverterParameter={StaticResource thiknessParameter}}"
RenderTransformOrigin="0.5,0.5"
Stroke="{Binding ElementName=root, Path=BorderBrush}"
StrokeThickness="{Binding ElementName=root, Path=ProgressThikness}">
<Ellipse.Resources>
<Storyboard x:Key="Storyboard">
<DoubleAnimation
RepeatBehavior="Forever"
Storyboard.TargetName="transform"
Storyboard.TargetProperty="Angle"
To="360"
Duration="0:0:20" />
<!-- Duration="0:0:1.8" this is record spped -->
</Storyboard>
</Ellipse.Resources>
<Ellipse.RenderTransform>
<RotateTransform x:Name="transform" />
</Ellipse.RenderTransform>
<Ellipse.Fill>
<ImageBrush ImageSource="{Binding Cover, ElementName=root, TargetNullValue={StaticResource FallbackCover}}" Stretch="UniformToFill" />
</Ellipse.Fill>
</Ellipse>
动画通过隐藏代码控制:
private static void IsPlayingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var me = d as NowPlayingDisk;
var elipse = me.CoverDisc;
if (elipse is null)
return;
var storyboard = elipse.Resources["Storyboard"] as Windows.UI.Xaml.Media.Animation.Storyboard;
if ((bool)e.NewValue)
{
if (storyboard.GetCurrentState() == Windows.UI.Xaml.Media.Animation.ClockState.Stopped)
storyboard.Begin();
else
storyboard.Resume();
}
else
storyboard.Pause();
}
除了不使用任何动画来减少内存占用外,我还能做什么?我注意到 dwm 过去消耗了超过 7Gb,几乎不可能使用机器。
我现在使用这个应用程序有一段时间了,我不确定这个问题是否一直存在。它过去确实运行了几个小时,至少我没有注意到任何东西消耗了这么多内存。
我在当前 Windows 版本的 Surface Pro 6 上运行:
Edition Windows 10 Home
Version 20H2
Installiert am 16.10.2020
Betriebssystembuild 19042.964
Leistung Windows Feature Experience Pack 120.2212.2020.0
Prozessor Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz 2.11 GHz
Installierter RAM 16,0 GB
Systemtyp 64-Bit-Betriebssystem, x64-basierter Prozessor
编辑
我能够在另一台运行旧版 Windows 的机器上对其进行测试。 在那台机器上,内存消耗完全没有问题。
Windows 10 Enterprise
Version 1908
Betriebssystembuild 17763.1879
如果正在播放音乐,关闭应用程序,由于使用了内存的storyboard对象,可能会导致storyboard对象无法释放。因此,我建议您可以在附加到 App 类的 Suspending 事件中释放内存对象。如下:
public App()
{
this.InitializeComponent();
this.Suspending += App_Suspending;
}
private void App_Suspending(Object sender, SuspendingEventArgs e)
{
storyboard.Pause();
}