我正在尝试创建一个具有播放列表选项的媒体播放器。当加载10-20首歌曲时没有问题。所以我尝试了一些要求更高的东西:我尝试加载 2048 首歌曲(我拿了几首歌曲并复制了很多次)。尝试将它们加载到我的媒体播放器中时,我的 CPU 和 Ram 内存增长了 95% 以上(仅加载了前 250 首歌曲),有一次我的电脑甚至重新启动。所以我试图通过使用不会让应用程序接管计算机的东西来减慢操作速度:如果 CPU 负载超过 85 % 并且内存负载超过 90 %,我会停止加载新歌曲(我使用 64 位操作系统与 Windows 8 如果这很重要)。一开始它以某种方式起作用,允许我加载近 600 首歌曲,然后:
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
The thread 'vshost.NotifyLoad' (0x1d0c) has exited with code 0 (0x0).
The thread 'vshost.LoadReference' (0x1e48) has exited with code 0 (0x0).
A first chance exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll
A first chance exception of type 'Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' occurred in Microsoft.VisualStudio.Debugger.Runtime.dll
最后,应用程序停止在“mscorlib.dll 中发生类型为 'System.OutOfMemoryException' 的未处理异常”。
现在解释一下“加载歌曲”在我的应用程序中的含义:
- 一个线程遍历从 OpenFileDialog 加载的每首歌曲,并检查文件的扩展名是否已知,如果已知(在本例中为:mp3),它将在队列末尾合并文件的路径。
- 另一个线程验证队列中是否有任何元素。
- 如果有,它会提取第一个元素,如果 CpuLoad 和 MemoryLoad(由另一个线程计算)不是太高,它会启动一个新线程来进行一些操作(在 4 中呈现)
- 进行操作的线程在 System.Windows.Media.MediaPlayer 类中加载歌曲并验证接下来的事情:文件的时间跨度,文件是否有音频,文件是否有视频,并记住这 3 个变量以及路径列表中的文件。
- 还有另一个线程验证是否有线程已完成其工作并将媒体文件添加到列表中,如果有,则删除对它们的引用,以便垃圾收集器处理它们。
“在 mscorlib.dll 中发生类型为 'System.OutOfMemoryException' 的未处理异常”出现在下一行:
MediaCreator[idx].CreatorThread.Start();
那将是启动处理歌曲的线程的行。所以我做了下一件事:在上面发布的行之前,我添加了Thread.Sleep(100);
. 它起作用了(这样做实际上导致加载了所有 2048 个文件),除了(根据我添加的秒表)加载所有歌曲需要 3 分 28 秒这一事实。另外,我知道 Thread.Sleep 通常不是推荐的方法,而且我知道同样的人甚至认为这是编程技能薄弱的证明(我以某种方式同意他们)。我也不想使用这种方法,因为它显然需要很长时间,而且在每台计算机/cpu/hdd/ram 上工作都是不可信的。为了证明这一点的不可信性,我使用 Sleep(10) 进行测试,它会很快失败,而使用 Sleep(20) 会加载近 1000 首歌曲,然后再次失败。我还尝试将 CPU 负载降低到 15%,将内存负载降低到 80%,
我还想提一下,Winamp 使用大约 11% 的 CPU(从 5% 到 16%)和不到 40 MB 的内存在 30 多秒内加载了所有文件。
所以我的问题是:我应该如何进行?我可以限制线程的数量,以便不超过 X 个线程以相同的类型运行,但这在我看来也是编程技能薄弱的证明,因为并非每个 CPU 都可以容纳相同数量的运行线程。所以我该怎么做 ?我真的需要从歌曲中获取这些细节 - 尽可能使用尽可能少的资源(知道它们有多长,以及它们是音频还是视频文件:在这里我应该提到我的应用程序也播放电影,它是只是我不认为任何人都需要在应用程序中一次加载数千部电影,如果我解决了音频问题,视频也将得到解决,因为歌曲仅在存储在列表中之前由电影区分- 所以没有什么会与我的问题的解决方案相冲突)。
编辑:我还附上了 ANTS Performance Profiles 显示的一些诊断信息: