我正在开发一个使用waveOut...
中的winmm.dll
API连续播放音频的应用程序。该应用程序使用“越级”缓冲区,它们基本上是一堆样本数组,您可以将它们转储到音频队列中。 Windows将按顺序无缝地播放它们,并且在每个缓冲区完成后,Windows会调用回调函数。在此函数中,我将下一组样本加载到缓冲区中,然后对其进行处理,然后将缓冲区转储回音频队列。这样,音频将无限期播放。
出于动画目的,我正在尝试将waveOutGetPosition
合并到应用程序中(因为“缓冲已完成”回调足够不规则,以致于会导致生涩的动画)。 waveOutGetPosition
返回当前的播放位置,因此非常精确。
问题在于,在我的应用程序中,对waveOutGetPosition
的调用最终会导致应用程序锁定-声音停止并且调用永不返回。我将事情归结为一个简单的应用程序来演示问题。您可以在此处运行该应用程序:
http://www.musigenesis.com/SO/waveOut%20demo.exe
如果您只是一遍又一遍地听到一小段钢琴的声音,那就可以了。这只是为了演示问题。这个项目的源代码在这里(所有内容都在LeapFrogPlayer.cs中):
http://www.musigenesis.com/SO/WaveOutDemo.zip
第一个按钮以跳过模式运行应用程序,而无需调用waveOutGetPosition
。如果单击此按钮,则该应用程序将一直播放而不会中断(X按钮将其关闭并关闭)。第二个按钮启动跳越器,还启动一个表单计时器,该计时器调用waveOutGetPosition
并显示当前位置。单击此按钮,该应用程序将运行一小段时间,然后将其锁定。在我的笔记本电脑上,它通常会在15-30秒内锁定;最多只花了一分钟。
我不知道如何解决此问题,因此我们将非常欢迎您提供任何帮助或建议。我发现有关此问题的帖子很少,但似乎存在潜在的死锁,可能是由于多次调用waveOutGetPosition
或同时发生的对此waveOutWrite
的调用。我可能经常调用此命令,以致系统无法处理。
编辑:忘记了,我正在Windows Vista上运行它。在其他操作系统上可能根本不会发生这种情况。
编辑2 :除以下(未答复)帖子外,我几乎没有在线找到有关此问题的信息:
http://social.msdn.microsoft.com/Forums/en-US/windowsgeneraldevelopmentissues/thread/c6a1e80e-4a18-47e7-af11-56a89f638ad7
编辑3 :好吧,我现在可以随意重现此问题。如果我在waveOutGetPosition
之后(在下面的代码行中)立即调用waveOutWrite
,则应用程序每次都会挂起。它也以一种特别糟糕的方式挂起-似乎将我的整个操作系统锁定了一段时间,而不仅仅是应用程序本身。因此,如果waveOutGetPosition
死锁与waveOutWrite
几乎在同一时间发生,而不仅仅是在字面上同时出现,那么它似乎会死锁,这可能解释了为什么锁对我不起作用。 Yeesh。
最佳答案
它在mmsys API代码内部陷入僵局。当主线程忙于执行waveOutWrite()时,在回调死锁中调用waveOutGetPosition()。它是可修复的,您将需要一个锁,以便这两个函数不能同时执行。将此字段添加到LeapFrogPlayer:
private object mLocker = new object();
并在GetElapsedMilliseconds()中使用它:
if (!noAPIcall)
{
lock (mLocker) {
ret = WaveOutX.waveOutGetPosition(_hWaveOut, ref _timestruct,
_timestructsize);
}
}
和HandleWaveCallback():
// play the next buffer
lock (mLocker) {
int ret = WaveOutX.waveOutWrite(_hWaveOut, ref _header[_currentBuffer],
Marshal.SizeOf(_header[_currentBuffer]));
if (ret != WaveOutX.MMSYSERR_NOERROR) {
throw new Exception("error writing audio");
}
}
这可能会有副作用,尽管我没有注意到。看看NAudio project.
下次创建项目的可上传.zip时,请使用Build + Clean。
关于c# - waveOutWrite和waveOutGetPosition死锁的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2452345/