c# - 如何使用System.Media.SoundPlayer异步播放声音文件?

标签 c# winforms audio

这是一个看似简单的问题:

在 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/

相关文章:

c# - Visual Studio 设计器 View 无法获得正确的形式

iphone - 音频直播到互联网

c# - 哪些 C# 数据类型可以是可空类型?

c# - NHibernate 缓存问题

c# - 从图像上绘制的文本中删除顶部和底部填充

ios - AVAudioPlayer 不会为一个 mp3 播放音频,但会为其他 mp3 播放音频?

ios - 将 AudioBufferList 转换为 CMSampleBuffer 会产生意外结果

c# - 对 Azure 队列调用 CreateIfNotExistsAsync() 的性能影响

c# - 抱歉,我们找不到 Test.xlsm。是否有可能被移动、重命名或删除?

c# - 将子控件 MouseMove 事件无缝转发给父控件