如何使用 System.Media.SoundPlayer 异步播放声音文件? [英] How to use System.Media.SoundPlayer to asynchronously play a sound file?

查看:48
本文介绍了如何使用 System.Media.SoundPlayer 异步播放声音文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

在 Windows 窗体中异步播放嵌入的 .wav 资源文件的正确方法是什么?

尝试 #1:

var player = new SoundPlayer();player.Stream = Resources.ResourceManager.GetStream("mySound");播放器播放();//注意 Play 是异步的

  • 好:不会阻塞 UI 线程
  • 差:SoundPlayer 和嵌入式资源流不是立即处置.

尝试 #2:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound")){使用 (var player = new SoundPlayer(audioMemory)){播放器播放();}}

  • 好:UI 线程没有被阻塞,SoundPlayer 和音频内存流被立即释放.
  • 差:比赛条件!Play() 是异步的,如果在 Play 完成之前处理了音频内存......抛出运行时异常.

尝试 #3:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound")){使用 (var player = new SoundPlayer(audioMemory)){player.PlaySync();}}

  • 好:立即处理播放器和音频流.
  • 坏处:PlaySync 阻塞了 UI 线程

尝试 #4:

ThreadPool.QueueUserWorkItem(ignoredState =>{使用 (var audioMemory = Resources.ResourceManager.GetStream("mySound")){使用 (var player = new SoundPlayer(audioMemory)){player.PlaySync();}}});

  • 好:UI 不会冻结,播放器和内存流会立即处理.
  • 不好:因为这经常触发,我们可能会用完线程池线程!请参阅拉里·奥斯特曼的 这段代码第 26 部分有什么问题.

看起来 SoundPlayer 应该有一个 PlayAsyncCompleted 事件.不幸的是,不存在这样的事件.我错过了什么吗?在 Windows 窗体中异步播放 .wav 嵌入资源的正确方法是什么?

解决方案

我没有足够的声誉来发表评论,所以我只会回答.

如果您对播放声音的要求看似简单"(您只想在单个 winform 用户执行某些操作时偶尔播放声音),那么我将使用上面的尝试 #4.

拉里·奥斯特曼 (Larry Osterman) 的这段代码第 26 部分有什么问题"让他的系统"在每次击键时分离出一个新的线程池线程(播放声音).他表示,在大约 15 秒的打字时间内,它会饱和默认的 500 个线程池大小,但这也是使用异步 RPC 的客户端/服务器应用程序也使用线程池.真的不是一个看似简单"的应用程序.

如果您尝试将声音字节每秒(或更快)排队 10 秒或 100 秒,那么它真的不是一个简单的应用程序",并且排队的线程/优先级子系统可能是有序的.

Here's a deceptively simple question:

What is the proper way to asynchronously play an embedded .wav resource file in Windows Forms?

Attempt #1:

var player = new SoundPlayer();
player.Stream = Resources.ResourceManager.GetStream("mySound");
player.Play(); // Note that Play is asynchronous

  • Good: doesn't block the UI thread
  • Bad: SoundPlayer and the embedded resource stream are not immediately disposed.

Attempt #2:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
    using (var player = new SoundPlayer(audioMemory))
    {
        player.Play();
    }
}

  • Good: UI thread is not blocked, SoundPlayer and audio memory stream are immediately disposed.
  • Bad: Race condition! Play() is async, and if audio memory gets disposed before Play is done...boom! Runtime exception is thrown.

Attempt #3:

using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
{
    using (var player = new SoundPlayer(audioMemory))
    {
        player.PlaySync();
    }
}

  • Good: Player and audio stream are immediately disposed.
  • Bad: PlaySync blocks the UI thread

Attempt #4:

ThreadPool.QueueUserWorkItem(ignoredState =>
  {
    using (var audioMemory = Resources.ResourceManager.GetStream("mySound"))
    {
        using (var player = new SoundPlayer(audioMemory))
        {
            player.PlaySync();
        }
    }
  });

  • Good: UI doesn't freeze, player and memory stream are immediately disposed.
  • Bad: Because this fires often, we may run out of thread pool threads! See Larry Osterman's what's wrong with this code part 26.

It seems like SoundPlayer should have a PlayAsyncCompleted event. Unfortunately, no such event exists. Am I missing something? What's the proper way to asynchronously play a .wav embedded resource in Windows Forms?

解决方案

I don't have enough reputation to comment so I'll just answer.

If your requirements to play sound are "deceptively simple" (you just want to play the occasional sound when a single winform user does something) then I would use Attempt #4 above.

Larry Osterman's "what's wrong with this code part 26" has his "system" spin off a new threadpool thread (to play sound) with each keystroke. He indicates than hammering away on it saturated the default 500 thread pool size in about 15 seconds of typing but this was also with a client/server app using async RPC that were also using the threadpool. Really not a "deceptively simple" application.

If you are trying to queue sound bytes every second (or faster) for 10s or 100s of seconds at a time then its really not a "simple application" and a queued threading/priority subsystem would probably be in order.

这篇关于如何使用 System.Media.SoundPlayer 异步播放声音文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆