这是一个看似简单的问题:
在 Windows 窗体中异步播放嵌入式 .wav 资源文件的正确方法是什么?
尝试 #1:
var player = new SoundPlayer();
player.Stream = Resources.ResourceManager.GetStream("mySound");
player.Play(); // Note that Play is asynchronous
- 好:不会阻塞 UI 线程
- 差:SoundPlayer 和嵌入式 资源流不是立即 处置。
尝试#2:
using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
using (var player = new SoundPlayer(audioMemory))
{
player.Play();
}
}
- 好:UI 线程未被阻塞,SoundPlayer 和音频内存流立即被释放。
- 差:比赛条件! Play() 是异步的,如果音频内存在 Play 完成之前被处理掉……砰!抛出运行时异常。
尝试 #3:
using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
using (var player = new SoundPlayer(audioMemory))
{
player.PlaySync();
}
}
- 好:立即处理播放器和音频流。
- 差:PlaySync 阻塞了 UI 线程
尝试 #4:
ThreadPool.QueueUserWorkItem(ignoredState =>
{
using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
using (var player = new SoundPlayer(audioMemory))
{
player.PlaySync();
}
}
});
- 好:UI 不会卡住,播放器和内存流会立即处理掉。
- 坏:因为这经常触发,我们可能会用完线程池线程!参见拉里奥斯特曼的 what's wrong with this code part 26 .
SoundPlayer 似乎应该有一个 PlayAsyncCompleted 事件。不幸的是,不存在这样的事件。我错过了什么吗?在 Windows 窗体中异步播放 .wav 嵌入式资源的正确方法是什么?
最佳答案
我没有足够的声誉来发表评论,所以我只是回答。
如果您对播放声音的要求“看似简单”(您只想在单个 winform 用户做某事时偶尔播放声音),那么我会使用上面的尝试 #4。
Larry Osterman 的“此代码第 26 部分有什么问题”让他的“系统”在每次击键时分拆出一个新的线程池线程(以播放声音)。他指出,在输入大约 15 秒后,默认的 500 线程池大小就会饱和,但这也适用于使用异步 RPC 的客户端/服务器应用程序,该应用程序也使用了线程池。确实不是一个“看似简单”的应用程序。
如果您尝试每秒(或更快)将声音字节排队 10 秒或 100 秒,那么它真的不是一个“简单的应用程序”,排队的线程/优先级子系统可能是有序的。
关于c# - 如何使用System.Media.SoundPlayer异步播放声音文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1161229/