gpt4 book ai didi

c# - waveOutWrite 和 waveOutGetPosition 死锁问题

转载 作者:行者123 更新时间:2023-11-30 21:22:00 25 4
gpt4 key购买 nike

我正在开发一个应用程序,它使用 winmm.dll 中的 waveOut... API 连续播放音频。该应用程序使用“leapfrog”缓冲区,这些缓冲区基本上是一堆样本数组,您可以将它们转储到音频队列中。 Windows 按顺序无缝地播放它们,并且当每个缓冲区完成时,Windows 调用一个回调函数。在这个函数中,我将下一组样本加载到缓冲区中,然后对其进行处理,然后将缓冲区转储回音频队列中。这样,音频就无限播放了。

出于动画目的,我正在尝试将 waveOutGetPosition 合并到应用程序中(因为“缓冲完成”回调非常不规则,足以导致动画不稳定)。 waveOutGetPosition 返回播放的当前位置,因此非常精确。

问题是,在我的应用程序中,调用 waveOutGetPosition 最终导致应用程序锁定 - 声音停止并且调用永远不会返回。我已经将事情归结为一个演示问题的简单应用程序。您可以在此处运行该应用:

http://www.musigenesis.com/SO/waveOut%20demo.exe

如果您只是一遍又一遍地听到一小段钢琴声,就说明它在起作用。这只是为了证明问题。这个项目的源代码在这里(所有内容都在 LeapFrogPlayer.cs 中):

http://www.musigenesis.com/SO/WaveOutDemo.zip

第一个按钮以 leapfrog 模式运行应用程序,而不调用 waveOutGetPosition。如果您单击此按钮,该应用程序将永远运行而不会中断(X 按钮将关闭它并关闭它)。第二个按钮启动 leapfrogger,还启动一个调用 waveOutGetPosition 并显示当前位置的表单计时器。单击此按钮,应用程序将运行一小会儿然后锁定。在我的笔记本电脑上,它通常会在 15-30 秒内锁定;最多只需要一分钟。

我不知道如何解决这个问题,所以非常欢迎任何帮助或建议。我发现关于这个问题的帖子很少,但似乎存在潜在的死锁,无论是对 waveOutGetPosition 的多次调用还是对它的调用和发生的 waveOutWrite同时。可能是我调用这个太频繁了,系统无法处理。

编辑:忘了说,我是在 Windows Vista 上运行的。这在其他操作系统上可能根本不会发生。

编辑 2:除了这些(未答复的)帖子外,我在网上几乎找不到关于这个问题的信息:

http://social.msdn.microsoft.com/Forums/en-US/windowsgeneraldevelopmentissues/thread/c6a1e80e-4a18-47e7-af11-56a89f638ad7

编辑 3:好吧,我现在可以随意重现这个问题了。如果我在 waveOutWrite 之后立即调用 waveOutGetPosition(在下面的代码行中),应用程序每次都会挂起。它还以一种特别糟糕的方式挂起 - 它似乎锁定了我的整个操作系统一段时间,而不仅仅是应用程序本身。因此,如果 waveOutGetPositionwaveOutWrite 发生在 几乎 同一时间,这似乎会发生死锁,而不仅仅是字面上的同时发生,这或许可以解释为什么这些锁对我不起作用。是的。

最佳答案

它在 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com