首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SoundPlayer的替代方案

SoundPlayer的替代方案
EN

Stack Overflow用户
提问于 2012-05-09 16:49:56
回答 1查看 2.4K关注 0票数 2

我使用SoundPlayer类在我的WPF应用程序中播放WAV文件。这些文件很短,是应用程序的一部分,是为了响应程序中发生的事件而播放的。用户无法控制播放的声音,也无法决定自己播放声音。我也尝试使用WPF MediaPlayer控件,但该控件有问题。SoundPlayer运行得很好,但是有一个问题。

本质上,我需要保持排队的声音,并播放一个接一个的声音,因为他们排队。在某些情况下,我必须停止任何声音正在播放,而是播放另一个声音。因此,我有两个与SoundPlayer控件相互排斥的要求:

  1. 我的代码需要知道声音什么时候播放完。
  2. 声音必须在后台播放

为了实现这一点,我创建了一个名为SoundController的类。它有一个后台线程,它使用ThreadDispatcher将调用排队到我用来播放声音的方法,使用BeginInvoke。该方法在调用SoundPlayer.PlaySync播放声音之前在SoundController事件中引发一个事件,然后在PlaySync返回后引发另一个事件。

在UI线程中,在需要停止声音的地方,我调用SoundController类的Stop方法。这就调用了SoundPlayerStop方法来停止播放声音。问题就在这里。事实证明,SoundPlayer.Stop并没有停止声音,但它在返回之前等待声音结束。

这会阻止我的GUI死掉。虽然我可以异步调用它,但我的GUI不会停止,但是声音也不会停止。

正如我所说的,WPF MediaPlayer不适合我们,而且无论如何,这都是过分的。还有其他的声音播放方式可以让我有能力发起事件,在后台线程中播放声音,并停止播放吗?

2012年6月26日编辑:

这件事在这里已经有一个多月了,我没有得到任何回应。因此,我想除了SoundPlayer控件之外,没有其他替代方法了。

我要从不同的角度提出一个新的问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-07-20 13:55:27

没有人回答这个问题,我已经超越了这个问题。因此,对于任何想知道的人来说,替代方案是MediaElement WPF控件和进行WIN32 API调用。

那我用的是哪种选择呢?都不是。

结果,对我来说,我不得不在我的SoundController类中添加第二个线程。第二个线程不运行Dispatcher;相反,它运行我在循环中编写的代码:

它最初在AutoResetEvent.

  • When上无限期地等待--引发AutoResetEvent,它启动一个while循环,以检查是否要播放一个声音。如果要播放一个声音,则执行

  • ,它在播放最后一个声音时循环,如果另一个声音被“排队”,它会播放那个声音。

  • 会重复,直到没有声音等待播放。H 215G 216

还有一点,但这不重要。在任何情况下,这似乎是正常的。因为声音是在一个单独的Thread上播放的,所以通过调用SoundPlayer.Stop方法,当前播放的声音可以从不同的Thread中中止。

编辑:

下面是我的代码的简化版本。我删除了一些特定的东西,我的程序的要求,与一个特殊的声音。这说明了基本流程是如何工作的。

代码语言:javascript
复制
private string NextSound { get; set; }
public AutoResetEvent PlayASoundFlag = new AutoResetEvent( false );
private Dictionary<string, SoundPlayer> Sounds { get; set; }
private object soundLocker = new object();
public string SoundPlaying { get; private set; }
public bool Stopping { get; set; }

public void PlaySound( string key, bool stopCurrentSound ) {
    if ( !Sounds.ContainsKey( key ) )
        throw new ArgumentException( string.Format( "Sound \"{0}\" does not exist", key ), "key" );

    lock ( soundLocker ) {
        NextSound = key;
        if ( SoundPlaying != null && stopCurrentSound )
            Sounds[ SoundPlaying ].Stop();
        PlayASoundFlag.Set();
    }
}

private void SoundController() {
    do {
        PlayASoundFlag.WaitOne();
        while ( !Stopping && NextSound != null ) {
            lock ( soundLocker ) {
                SoundPlaying = NextSound;
                NextSound = null;
            }
            Sounds[ SoundPlaying ].PlaySync();
            lock ( soundLocker )
                SoundPlaying = null;
        }
    } while ( !Stopping );
}

当程序启动时,类将键和声音文件加载到Sounds Dictionary中。这样,用户所要做的就是将他们想要播放的声音的键传递给PlaySound方法。

如果愿意,可以将NextSound属性替换为QueuePlaySound方法必须对要播放的声音的键进行排队,而SoundController线程必须将每个键从while循环中的线程中排出,当Queue中什么都没有了时退出。

最后,当程序停止时,您需要将Stopping标志设置为true &设置PlayASoundFlag,以便代码从循环中出来。这将导致SoundController线程停止。

我将初始化Dictionary和启动线程留给您。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10520548

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档