0

第一次发帖,温柔点;-)

我正在编写一个音频应用程序(在 C++ 中),它作为 Windows 服务运行,使用 WASAPI 从插孔中的线路中获取样本,并对其进行一些处理。

我注意到,当我的应用程序“录制”时,Windows 不会自动挂起或休眠。

我已经注册了电源事件通知,如果我自己按下暂停按钮,我的服务会获得适当的电源事件并正常处理它们。如果我让系统自行挂起,则永远不会收到电源事件。

如果我删除了引用 WASAPI 的代码位,则在手动和自动挂起时都会正常接收电源事件。所以似乎有一些关于使用 WASAPI 告诉 Windows 忽略自动挂起计时器的东西。

谁能帮助解释这种行为,我能做些什么来阻止它吗?我不希望我的应用程序成为行为不端并阻止系统暂停的应用程序之一。

4

4 回答 4

5

不幸的是,没有任何机制可以做你想做的事——打开音频流可以防止电源状态转换,就像通过网络打开文件和许多其他事情一样。

这是音频驱动程序 (portcls.sys) 的功能,而不是 WASAPI,也不是 Vista 的新行为——我相信 XP 和 Win2K 有类似的行为(尽管电源状态转换在 Vista 上比在 XP 上可靠得多和 Win2K,因此用户倾向于更多地依赖它们)。

在 Windows 7 上,您可以使用“powercfg -requests”来查找系统的任何部分是否阻止机器进入睡眠状态。更多信息可以在这里找到

于 2009-03-17T02:01:17.027 回答
3

非常感谢拉里确认这种行为是设计使然,而不是我在做一些愚蠢的事情。

为了解决这个问题,我使用了 Win32 CallNtPowerInformation()API 来检索系统空闲计时器:

SYSTEM_POWER_INFORMATION spi = {0};
NTSTATUS status = CallNtPowerInformation(SystemPowerInformation, NULL, 0, 
                                         &spi, sizeof(spi));

if (NT_SUCCESS(status) && (spi.TimeRemaining==0))
{
    // should have gone to sleep
}

成员从用户在控制面板中指定的时间(例如“1 小时后系统待机” spi.TimeRemaining)开始倒计时(以秒为单位),并在 CPU 使用率(以百分比表示)超过 时重置spi.MaxIdlenessAllowed

如果spi.TimeRemaining达到零,系统应该已经进入睡眠状态,所以我关闭我所有的 WASAPI 句柄并让它这样做。

于 2009-04-09T12:03:40.503 回答
0

我相信电源管理 API 中有一个功能,它允许应用程序告诉操作系统它不希望系统在一段时间内进入省电模式(我认为这是一个开/关类型的功能)。如果 WASAPI 中的某些东西正在调用该方法,那么您可能无能为力。这对硬件按钮行为是有意义的,因为电源管理服务不会根据电源模式的激活方式来强制执行应用程序请求。

至于解决方法,我不知道。我可能会尝试的一件事是从电源管理 API 读取节电超时信息,然后在系统接近节电阈值时暂停录制;我不知道那会有多难。祝你好运。:)

于 2009-03-13T18:22:54.400 回答
0

我可能会尝试的一件事是从电源管理 API 读取节电超时信息,然后在系统接近节电阈值时暂停录制;

一个好主意——但我认为这很难。省电超时应该可以使用电源管理 API 读取,但您还需要知道当前用户输入的空闲状态,这是无法从 Windows 服务读取的。

于 2009-03-14T09:39:12.323 回答