Windows runtime Windows Phone 8.1中的媒体管道是否中断?

Windows runtime Windows Phone 8.1中的媒体管道是否中断?,windows-runtime,windows-phone,windows-store-apps,windows-phone-8.1,background-audio,Windows Runtime,Windows Phone,Windows Store Apps,Windows Phone 8.1,Background Audio,Windows Phone 8.1中的媒体管道似乎因大量内存管理问题而中断 当您在Windows Phone Runtime 8.1中创建使用IMediaSource来流式传输音频的后台音频应用程序时,该应用程序的组件最终会抛出OutOfMemoryException,在某些情况下甚至会抛出StackOverflowException。当查看内存转储时,内存中有很多未收集的垃圾 讨论已经开始并进展到这一结论。为了让Windows Phone团队能够注意到这一点,我已经创建了一个程序,但我仍然希望

Windows Phone 8.1中的媒体管道似乎因大量内存管理问题而中断

当您在Windows Phone Runtime 8.1中创建使用IMediaSource来流式传输音频的后台音频应用程序时,该应用程序的组件最终会抛出OutOfMemoryException,在某些情况下甚至会抛出StackOverflowException。当查看内存转储时,内存中有很多未收集的垃圾

讨论已经开始并进展到这一结论。为了让Windows Phone团队能够注意到这一点,我已经创建了一个程序,但我仍然希望是我(和其他来自MSDN论坛的家伙)错了,并且有一个解决方案

我也有一个小问题,它也受到这个问题的困扰,关于这个问题,实际上有一个小问题

我希望在社区的帮助下,这个问题能够得到解决,或者直接传递给微软开发团队进行调查和消除。谢谢

更新1:


有一个问题,但它无助于防止OutOfMemoryException。

他们在MSS管理内存的方式上有内存问题,但他们在一些更新过程中悄悄地修复了它:

我不确定,但我认为问题在于你的代码。您不应该调用
var buffer=new byte[4096]每次请求样本时。这样做可能在PC上工作,但对于嵌入式平台,我认为对内存管理器强调太多不是一个好主意


在我的MediaStreamSource实现中,我使用在构建MSS时分配的单个循环缓冲区,并且缓冲区的部分在回放期间被无限重用。在我的GetSamPleaseSync中,我构造了我的流实现类的一个实例,它不拥有任何内存,而是只持有对该循环缓冲区一部分的引用。这样,在播放过程中只分配/取消分配了几个小对象,因此音频流数据不会加载内存管理器。

好的,因此问题似乎实际上是字节数组在.NET中的生存期

为了解决内存问题,应该使用Windows运行时的
Windows.Storage.Streams.IBuffer
。不要以任何形式创建许多新的.NET字节数组,无论是通过简单的
newbyte[]
,还是使用类,因为它是
IBuffer
接口的托管实现

这些字节数组一旦被分配,就会因被
OverlappedData
结构固定而长寿,并溢出后台音频任务的内存阈值
IBuffer
s(真正的Windows运行时数组,如类)包含本机数组,只要
IBuffer
的引用计数达到0(零),它们就不依赖GC

我发现这个问题不仅仅是背景音频的问题。事实上,我已经看到了很多关于类似问题的其他问题。解决方案是在可能的情况下使用Windows Runtime backend,因为它是非托管的,并且在资源没有引用时立即释放资源


感谢@Soons为我指明了正确的方向

这是有道理的。尽管我说的是Windows Phone 8.1运行时应用程序,它使用另一个(基于Media Foundation),与Silverlight的稍有不同。它缓冲整个流并同时播放(我看到它在处理第一个样本之前请求了132个样本),所以我不太确定如何确定循环缓冲区的最佳大小。一些代码片段将受到高度赞赏:)此外,Silverlight的MediaStreamSource实现工作完美,尽管它在每次调用GetSamPleaseSync时都会分配一个缓冲区。您的132个示例仅为528 kb—不到3秒的未压缩CD质量音频。操作系统音频子系统内部也有一些缓冲。Silverlight和WinRT是不同的平台。很有可能,CLR或音频支持中的细微变化导致您的非最佳解决方案停止在WinRT上工作。此外,现在在WinRT中有一个MediaStreamSample.Processed事件,您可以处理该事件以重用循环缓冲区的部分(在Silverlight中,我依赖操作系统在我的示例流上调用的Stream.Read方法来标记缓冲区的部分空闲)。除非使用循环缓冲区,否则我看不到处理此事件的任何其他理由。这是正确的,但我尝试了这样做,系统实际上请求样本的速度比处理样本的速度快(这很明显),因此这种方法毫无用处。我现在所能想到的是单个
字节[4096]
缓冲区和多个
InMemoryRandomAccessStream
的组合,我相信它们(因为它们是本机类)会在Dispose上清除内部缓冲区内存。