waveOutWrite 和 waveOutGetPosition 死锁问题

2024-04-17

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

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

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

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

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

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

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

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

Edit:忘了提及,我在 Windows Vista 上运行它。在其他操作系统上可能根本不会发生这种情况。

Edit 2:除了这些(未答复的)帖子之外,我在网上几乎找不到有关此问题的信息:

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

Edit 3: 嗯,我现在可以随意重现这个问题了。如果我打电话waveOutGetPosition之后立马waveOutWrite(在下面的代码行中)应用程序每次都会挂起。它也以一种特别糟糕的方式挂起 - 它似乎锁定了我的整个操作系统一段时间,而不仅仅是应用程序本身。所以看来waveOutGetPosition如果死锁发生在nearly同时waveOutWrite,不仅仅是字面上的同时,这可能解释了为什么锁对我不起作用。是的。


它在 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 项目。 http://www.codeplex.com/naudio

下次创建项目的可上传 .zip 时,请使用“构建 + 清理”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

waveOutWrite 和 waveOutGetPosition 死锁问题 的相关文章

  • 当我在 C 中将 long int 赋值给 int 时会发生什么?

    在最近的作业中 我被告知要使用long变量来存储结果 因为它可能是一个很大的数字 我决定在我的系统 英特尔酷睿 i5 64 位 Windows 7 gnu gcc 编译器 上检查这对我来说真的很重要 并发现以下代码 printf sizeo
  • C 中的隐秘结构定义

    我遇到了以下情况迷宫定义 https github com gduarte lkb blob master code stack maze h code typedef struct mazeNode int hasCheese int t
  • 返回带有列表对象的列表对象

    我有三个表 汽车品牌 汽车型号 和 CarsandModel 我有 Carsand 模型表 因为一个模型可以由多个制造商构建 我想返回包含汽车型号列表的汽车品牌列表 我现在的长篇大论不是过滤汽车型号的汽车制造商列表 我尝试添加一个 wher
  • 任何reinterpret_cast改变指针值的真实例子?

    根据 C 标准 reinterpret cast一个指针的T 到其他类型的指针Q 可以改变或不改变指针值 https stackoverflow com questions 1863069 casting via void instead
  • Java 相当于 C# 的 async/await?

    我是一名普通的 C 开发人员 但偶尔也会使用 Java 开发应用程序 我想知道 Java 中是否有相当于 C async await 的东西 简单来说 java 相当于 async Task
  • 计算序列而无法存储值?

    问题陈述 here http www spoj com problems EC SER 令 S 为无限整数序列 S0 a S1 b Si Si 2 Si 1 对于所有 i gt 2 你有两个整数 a 和 b 您必须回答有关序列中第 n 个元
  • 如何使用 LINQ 对列表的列表进行分组(例如:List>)

    我知道我可以使用一些 for 循环轻松地做到这一点 但想看看是否有一种方法可以使用流畅的 LINQ 来做到这一点 我试图找出每个子列表中有多少个 我在看Enumerable SequenceEqual http msdn microsoft
  • 是否可以将 CMFCToolBar 添加到对话框中?

    我刚刚尝试了将 CToolbar 添加到新 CMFCToolBar 上的对话框的标准方法 但这不起作用 在我深入研究新的实现之前 我想知道它是否真的可行 我不确定你所说的 标准方式 是什么意思 但你当然可以以编程方式做到这一点 In MyD
  • 如何在提升日期时间中忽略周末和节假日?

    第一个问题 我有一个提升日期对象 如下所示 boost gregorian date 今天 2012 02 13 我从今天减去日期部分 如下所示 今天 月 240 或今天 天 X 等 我想在进行上述减法时是否有办法排除周末和特殊假期 我的意
  • Web API 2 中的方法名称约定 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 是否有 Web API 2 中使用的约定的列表 以这两种方法为例 两者都可以工作 但都没有用属性来装饰 IHttpActionResu
  • 使用 C 通过引用传递数组

    是的 我已经阅读了这个问题和答案 在 C 中通过引用传递数组 https stackoverflow com questions 1106957 pass array by reference in c 我有一个类似的问题 并从该问题中实现
  • 将 LPTSTR 转换为要写入文件的字符串或 char *

    我想将 LPTSTR 转换为字符串或 char 以便能够使用 ofstream 将其写入文件 有任何想法吗 Use T2A http msdn microsoft com en us library 87zae4a3 VS 80 aspx宏
  • MonoMac 窗口关闭时没有错误

    我刚刚开始在 Xamarin Studio 中使用 MonoMac 并且遇到了最奇怪的问题 我有一个带有 NSButton 和 NSTextField 的窗口 至此 我已经删除了按钮上的事件处理程序 因此它不会执行任何操作 除了在单击它时突
  • 如何收集和存储tellp()、tellg()返回类型?

    我正在编写一个在文件中维护 linked list 的程序 因此 我通过使用tellp tellg 遍历文件并将其添加到特定的长整数 可以视为偏移量 以到达新位置 一个简单的例子是 long next offset sizeof long
  • 使用循环在 C 中管道传输两个或多个 shell 命令

    我正在尝试执行ls wc l通过 C 语言程序 而不是使用命令行 这是我当前的工作代码 int main int pfds 2 pipe pfds pid t pid fork if pid 0 The child process clos
  • timeval_subtract 解释

    使用 timeval subtract 函数来查找两个 struct timeval 类型之间经过的时间 有人可以解释一下用于 通过更新 y 执行后续减法的进位 和其他部分的目的和逐步数学吗 我了解该函数的目的以及如何在程序中实现它 但我想
  • 并排显示图像的一半 - OpenGL

    我为两个图像创建了两个纹理 现在我想在opengl中按图像2的左侧部分 完整的图像1 图像2的右侧部分的顺序显示该纹理 我已经做了如下 Image1 显示在 opengl 屏幕的中央 但屏幕的左右部分不正确 应分别显示 image2 的左侧
  • 如何将curlpp 添加到我的项目中?

    我正在尝试从 vb net 过渡到 C 但我陷入了困境 我从下载了curpp这给了我一个 dll exp 和 lib 文件 我将包含这 3 个文件的目录添加到项目属性中的 附加库目录 链接器 gt 常规 接下来 我将 ws2 32 lib
  • 如何在 C# 中使用 Selenium WebDriver 获取当前窗口的 URL?

    在我的应用程序中 登录时 它会导航到另一个页面 现在我需要在 selenium C 中使用 WebDriver 获取新的 URL 我找不到任何函数来执行此操作 我努力了driver Url driver getLocation and dr
  • 同时使用多个控制台

    是否有捷径可寻 我现在仅使用控制台测试我的网络应用程序 最好的办法是从一个项目中拥有多个控制台 然后按一下 立即调试 菜单项 我可以像过去一样使用多个项目 但这似乎很笨拙 理想情况下 我可以启动多个控制台实例 从同一线程运行很好 并且让它们

随机推荐

  • 无法在 gitlab-ci runner 上运行最新的 docker

    我正在测试 gitlab ci 并尝试从 Dockerfile 在注册表上生成图像 我有相同的代码只是为了测试 gitlab ci image docker latest tages build deploy build applicati
  • 如何从向量或数组中随机选择一个元素?

    我有一个向量 其中元素是 String String 我如何随机选择这些元素之一 你想要的rand https crates io crates rand 板条箱 特别是choose https docs rs rand 0 7 2 ran
  • 如何从 Laravel 资源控制器中删除 show() 函数

    我的 Laravel 项目中有资源控制器 Route Route resource products ProductsController 在 ProductController 中 我不想使用show id 函数 因为我的项目中不需要这个
  • 未捕获的类型错误:无法读取未定义的属性“draw”

    for var i 0 i lt reduced length i var innerdata for var j 0 j lt days length j var rev 0 each reduced i data function ti
  • 如何替换 Google 云端硬盘中的文件?

    使用以下代码 该代码取自android 快速入门 如果您拍摄多张照片 此代码可以生成多个同名文件 如何修改才能保证同名文件被替换呢 public class MainActivity extends Activity implements
  • 带箭头的线图

    我有一个折线图 我想使用箭头而不是线条来绘制 也就是说 连续的点对之间的线应该是从第一个点到第二个点的箭头 我知道的arrow功能 但这似乎只做单个箭头 在我找到一种方法来尝试使用它来完成整个情节之前 是否有更好的方法来做到这一点 你可以这
  • TortoiseHg无法提交--“系统找不到指定的文件”

    我刚刚选择了 TortoiseHg 用于 Windows 上的分布式源代码控制 并将其安装在我的 C 驱动器上 然后我创建了一个存储库 位于 D projects 中 当我尝试提交更改时 它给了我错误 abort None 系统找不到 指定
  • 应用程序未安装在模拟器上:警告:打开音频输入失败

    我创建了一个 你好 项目 我没有更改 eclipse 生成的默认模板的任何内容 然后我运行了该应用程序 我没有收到任何错误 但是 该应用程序并未安装在模拟器上 环境 windows7 x64 jdk 7u7 windows x64 inst
  • 获取ASP.NET网站用户的MAC

    我正在寻找一种解决方案来查找使用 asp net 网站的用户的 MAC 号码 我知道你可以获得一个IP地址 不知道为什么 但它不会很复杂 但是我可以找出具有该IP的MAC地址吗 编辑 我的意思是在 NET中以编程方式 而不是手动 IP 地址
  • Godoc 文档不输出列表

    在整个项目中 我负责测试和记录 为函数和方法创建了文档 格式如下 CheckPermissionArray checks that values is an array that contains the expectedValue Par
  • Android 模拟器无法在 Eclipse 中启动

    我刚刚安装了整个 shebang 以便在 Eclipse 中开发 Android 应用程序 我运行的是 64 位 gentoo 一切似乎都很顺利 我创建了开发组的 hello world 示例 package com nfshost fly
  • 如何调整 svg 的大小(使用蜡染)并显示它?

    我有一个 100x100 像素的 svg 文件 例如 我正在使用蜡染 如果我做一个 JSVGCanvas svg new JSVGCanvas svg setSize 10 10 它只会显示图片的这一部分 而不显示调整大小的图像 你知道如何
  • 如何在 Core Data 中进行 NSManagedObject 的深度复制

    我正在尝试复制核心数据中现有的 NSManagedObject 和相关子对象 我似乎找不到一个简单的方法来做到这一点 我有一个从核心数据数据库填充的 NSArrayController 我想获取 SelectionIndex 处的对象并进行
  • 从 Zend Framework 2 中的路由获取 $_GET 参数

    Zend Framework 1 有一种非常简单的方法来解析 URL 路由并在 GET 超全局中设置找到的参数以便于访问 当然 您可以在控制器内使用 gt getParam something 但如果在 URL 中找到参数 则它是also可
  • 独立脚本可以为绑定到电子表格的另一个脚本创建触发器吗?

    我正在尝试为电子表格绑定脚本创建一个可安装的 onEdit 触发器 我想使用单独的独立脚本以编程方式执行此操作 根据文档看来这应该是可能的 请注意 与简单的 onOpen 触发器不同 可安装触发器的脚本不需要绑定到电子表格 要从独立脚本创建
  • 今天的google doodle世界博览会是如何实现的? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我想知道它
  • Javascript,CSS:将变换原点更改为手势更改的中心点

    我想将变换原点更改为捏合手势的中心点 此工作代码 safariDevSample 应用缩放和旋转而不改变transform origin window angle 0 global to store data for later reset
  • ValidationError:选项对象无效。复制插件已使用与 API 架构不匹配的选项对象进行初始化

    由于存在漏洞 我刚刚更新了 package json 中的一些包 所有漏洞均已修复 但当我执行 npm run 时出现以下错误 复制插件包在我的漏洞修复过程中得到了更新 我尝试从旧提交中复制 package json 并重新安装所有软件包
  • 对 F# 联合类型列表进行操作

    这是我的问题的延续F 联合类型列表 https stackoverflow com questions 13770911 f list of union types 感谢有用的反馈 我能够创建一个列表Reports with Report要
  • waveOutWrite 和 waveOutGetPosition 死锁问题

    我正在开发一个使用连续播放音频的应用程序waveOut API来自winmm dll 该应用程序使用 leapfrog 缓冲区 它基本上是一堆转储到音频队列中的样本数组 Windows 按顺序无缝播放它们 并且当每个缓冲区完成时 Windo