Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
515 views
in Technique[技术] by (71.8m points)

c# - How to use System.Media.SoundPlayer to asynchronously play a sound file?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...