我正在使用ThreadPool.QueueUserWorkItem播放一些声音文件,并且在播放时不会挂断图形用户界面。
它是有效的,但有一个不受欢迎的副作用。
在执行QueueUserWorkItem CallBack过程时,没有任何东西可以阻止它启动一个新线程。这会导致线程中的样本重叠。
我如何才能让它等待已经运行的线程完成运行,然后才运行下一个请求?
编辑:private object sync = new Object(); lock (sync) { .......do sound here }
这是可行的。按顺序播放声音。
但是当我在播放的声音结束之前不断发送声音请求时,一些样本会被播放多次。将会进行调查。
编辑:上面的结果是Lock Convoy @Aaronaught提到的吗?
发布于 2010-03-29 03:11:49
这是一个典型的线程同步问题,在这种情况下,有多个客户端都希望使用相同的资源,并且需要控制它们访问该资源的方式。在这种情况下,音响系统愿意同时播放多个声音(这通常是可取的),但由于您不希望出现这种行为,因此可以使用标准锁定来访问声音系统:
public static class SequentialSoundPlayer
{
private static Object _soundLock = new object();
public static void PlaySound(Sound sound)
{
ThreadPool.QueueUserWorkItem(AsyncPlaySound, sound);
}
private static void AsyncPlaySound(Object state)
{
lock (_soundLock)
{
Sound sound = (Sound) state;
//Execute your sound playing here...
}
}
}其中Sound是用来表示要播放的声音的任何对象。当多个声音竞争播放时间时,这种机制是“先到先得”。
正如在另一个响应中提到的,要小心过度的“堆积”声音,因为你会开始占用ThreadPool。
发布于 2010-03-29 02:25:41
您可以使用具有队列的单个线程来播放所有声音。
当您想要播放一个声音时,将一个请求插入到队列中,并通知播放线程有一个新的声音文件要播放。声音播放线程看到新请求并播放它。一旦声音结束,它将检查队列中是否还有声音,如果还有声音,则播放下一个声音,否则将等待下一个请求。
这种方法的一个可能的问题是,如果你有太多的声音需要播放,你可能会得到一个不断增长的积压,因此声音可能会延迟几秒钟甚至几分钟。为了避免这种情况,您可能希望对队列大小进行限制,并在队列太多时删除一些声音。
发布于 2010-03-29 03:02:41
您可以编写的最简单的代码如下:
private object playSoundSync = new object();
public void PlaySound(Sound someSound)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
lock (this.playSoundSync)
{
PlaySound(someSound);
}
}));
}虽然非常简单,但它可能会产生问题:
在实践中,只有当你频繁地播放大量声音或声音非常长时,这些问题才是相关的。
https://stackoverflow.com/questions/2533966
复制相似问题