我使用SoundPlayer类在我的WPF应用程序中播放WAV文件。这些文件很短,是应用程序的一部分,是为了响应程序中发生的事件而播放的。用户无法控制播放的声音,也无法决定自己播放声音。我也尝试使用WPF MediaPlayer控件,但该控件有问题。SoundPlayer运行得很好,但是有一个问题。
本质上,我需要保持排队的声音,并播放一个接一个的声音,因为他们排队。在某些情况下,我必须停止任何声音正在播放,而是播放另一个声音。因此,我有两个与SoundPlayer控件相互排斥的要求:
为了实现这一点,我创建了一个名为SoundController的类。它有一个后台线程,它使用Thread的Dispatcher将调用排队到我用来播放声音的方法,使用BeginInvoke。该方法在调用SoundPlayer.PlaySync播放声音之前在SoundController事件中引发一个事件,然后在PlaySync返回后引发另一个事件。
在UI线程中,在需要停止声音的地方,我调用SoundController类的Stop方法。这就调用了SoundPlayer的Stop方法来停止播放声音。问题就在这里。事实证明,SoundPlayer.Stop并没有停止声音,但它在返回之前等待声音结束。
这会阻止我的GUI死掉。虽然我可以异步调用它,但我的GUI不会停止,但是声音也不会停止。
正如我所说的,WPF MediaPlayer不适合我们,而且无论如何,这都是过分的。还有其他的声音播放方式可以让我有能力发起事件,在后台线程中播放声音,并停止播放吗?
2012年6月26日编辑:
这件事在这里已经有一个多月了,我没有得到任何回应。因此,我想除了SoundPlayer控件之外,没有其他替代方法了。
我要从不同的角度提出一个新的问题。
发布于 2012-07-20 13:55:27
没有人回答这个问题,我已经超越了这个问题。因此,对于任何想知道的人来说,替代方案是MediaElement WPF控件和进行WIN32 API调用。
那我用的是哪种选择呢?都不是。
结果,对我来说,我不得不在我的SoundController类中添加第二个线程。第二个线程不运行Dispatcher;相反,它运行我在循环中编写的代码:
它最初在AutoResetEvent.
AutoResetEvent,它启动一个while循环,以检查是否要播放一个声音。如果要播放一个声音,则执行
H 215G 216还有一点,但这不重要。在任何情况下,这似乎是正常的。因为声音是在一个单独的Thread上播放的,所以通过调用SoundPlayer.Stop方法,当前播放的声音可以从不同的Thread中中止。
编辑:
下面是我的代码的简化版本。我删除了一些特定的东西,我的程序的要求,与一个特殊的声音。这说明了基本流程是如何工作的。
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属性替换为Queue。PlaySound方法必须对要播放的声音的键进行排队,而SoundController线程必须将每个键从while循环中的线程中排出,当Queue中什么都没有了时退出。
最后,当程序停止时,您需要将Stopping标志设置为true &设置PlayASoundFlag,以便代码从循环中出来。这将导致SoundController线程停止。
我将初始化Dictionary和启动线程留给您。
https://stackoverflow.com/questions/10520548
复制相似问题