【问题标题】:Memory Leak on UWP MediaPlayer (Windows.Media.Playback.MediaPlayer)UWP MediaPlayer (Windows.Media.Playback.MediaPlayer) 上的内存泄漏
【发布时间】:2019-03-11 04:57:23
【问题描述】:

我正在维护一个 WPF 应用程序。我在我的项目中添加了一个 UWP 媒体播放器。但是,内存使用率太高了。我意识到 UWP 媒体播放器做到了,所以我创建了一个可重现的代码。

while (true)
{
    var mp = new MediaPlayer()
    {
        Source = MediaSource.CreateFromUri(new Uri("Test.mp4"))
    };
    Thread.Sleep(1000);
    mp.Play();
    Thread.Sleep(1000);
    mp.Dispose();
}

此代码发生内存泄漏。我创建了 MediaPlayer 并处理了它!但是,它的内存使用量会无限增长。

如何发现这段代码的内存泄漏?

这是 .NET Core 3.0 项目。 (带有 WPF 的 XAML 岛)我还没有测试它是否出现在纯 UWP 项目中。

有人说这是自然的,因为它是一个循环。但是,下面的代码不会造成任何内存泄漏,因为 GC 有效。 (当然,一些(但限制性的)参考文献不会被收集。)

while (true)
{
    new SomeClass();
}

【问题讨论】:

  • 你还没有运行 GC。你需要运行它并设置收集大对象的选项以确保根本没有任何泄漏。
  • 我调用了 System.GC()。但是,它没有收集到。

标签: xaml uwp


【解决方案1】:

这绝对是 Windows 10 19H1 的 bug。因为内置应用程序(电影和电视)具有相同的内存泄漏问题。要重现这一点,只需重复打开的视频文件并关闭它。

【讨论】:

  • 我可以确认这一点!我已经循环播放了几分钟的视频,内存确实从大约 300mb 上升到了 1037mb,并且还在不断上升。
【解决方案2】:

您的代码写入方式内存会膨胀和增长,直到您耗尽内存。我也在纯 UWP 中进行了验证。如果你进行以下两个更改,你会发现内存会保持稳定,并且系统会在每次循环后回收所有内存:

  1. 同时释放您创建并分配给 Source 属性的 MediaSource 对象
  2. 不要在一个紧密的循环中运行它,而是将自己作为调度程序操作调用

这是未显示任何泄漏的代码(在 UWP 中测试)。在 WPF 中,Dispatcher 调用看起来会略有不同:

private async void PlayMedia()
{
    var ms = MediaSource.CreateFromUri(new Uri("ms-appx:///Media1.mp4"));
    var mp = new MediaPlayer()
    {
        Source = ms
    };
    Thread.Sleep(1000);
    mp.Play();
    Thread.Sleep(1000);
    mp.Dispose();
    ms.Dispose();

    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, new DispatchedHandler(PlayMedia));
}

附带说明:如果 SomeClass 是纯托管代码类,则您提到的“SomeClass”比较并不完全是苹果对苹果的比较,因为您在此处创建的对象是复杂的本机 Windows 运行时对象它们周围只有一个精简的托管代码包装器。

现在也在 WPF 中进行了测试:我重现了原始内存增长问题,然后应用建议的更改并验证内存不再增长。这是我的测试项目供参考:https://1drv.ms/u/s!AovTwKUMywTNuLk9p3frvE-U37saSw

我还运行your shared solution,将 WPF 应用程序打包为 Windows 应用程序包,并且我没有看到最新发布的 Windows 10 (17763.316) 版本存在泄漏。下面是运行您的解决方案一段时间后的内存诊断屏幕截图。如果这是特定于您正在运行的内部版本,请通过反馈中心记录错误。我认为此时我们应该按照已回答的方式结束这个问题。

【讨论】:

  • 我已经试过了。但是,它会泄漏。我认为如果它没有发生在 UWP 中,它可能是 XamlIsland 的一个错误(处于预览阶段)。
  • 您的复制代码实际上根本不涉及 XamlIslands。我刚刚根据您在问题中提供的代码测试了该场景,并确认我建议的代码更改也适用于 WPF 案例。这是我的测试项目:1drv.ms/u/s!AovTwKUMywTNuLk9p3frvE-U37saSw - 如果这不能为您解决问题,请分享一个完整的重现项目来演示该问题。
  • 谢谢。我意识到 UWP 媒体播放器可以在没有 XAML 岛的情况下使用。顺便说一句,我仍然无法理解为什么会这样。我认为即使在紧密循环中也不应该有内存泄漏,因为我调用了 Dispose()。而且,我发现你和我的代码都没有导致内存泄漏。 (抱歉)但是,如果我创建 WAP(Windows 应用程序打包)项目,它就会泄漏。不同的是,纯WPF项目没有任何声音,但WAP项目在视频文件中播放音频。哦,我正在使用带有预览版 SDK 的 Windows Insider Preview 19H1 (Build 18334.1)。
  • 这是一个完整的示例解决方案文件。再次感谢。 drive.google.com/open?id=1-FU9ci9E8DeD3IKXmcDM4OWfYxs6sKJn
  • 那么,即使在应用了建议的更改之后,WAP 也会泄漏?如果是这样,请将该信息添加到问题中 - 或关闭此信息并打开一个新问题以便清楚起见。这个问题没有提到任何关于 WAP 或 19H1 的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-14
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 2021-01-14
  • 2018-08-24
相关资源
最近更新 更多