WASAPI мешает Windows автоматически приостанавливать? - PullRequest
0 голосов
/ 13 марта 2009

Первый раз постер, будь нежнее; -)

Я пишу аудио-приложение (на C ++), которое работает как служба Windows, использует WASAPI для выборки из линии в гнезде и выполняет некоторую обработку на нем.

Что-то, что я заметил, это то, что, когда мое приложение «записывает», Windows не будет автоматически приостанавливаться или переходить в спящий режим.

Я зарегистрировался для уведомлений о событиях питания, и, если я сам нажму кнопку приостановки, мой сервис получит соответствующие события питания и обработает их в порядке. Если я оставлю систему, чтобы приостановить ее самостоятельно, события питания никогда не будут получены.

Если я удаляю биты кода, где я ссылаюсь на WASAPI, события питания принимаются как обычно как при ручном, так и при автоматическом приостановлении. Похоже, что в WASAPI есть что-то, что заставляет Windows игнорировать таймер автоматического приостановления.

Может ли кто-нибудь помочь объяснить это поведение, и могу ли я что-нибудь сделать, чтобы остановить его? Я не хочу, чтобы мое приложение было одним из тех, которые плохо себя ведут и не позволяют системам зависать ..

Ответы [ 4 ]

5 голосов
/ 17 марта 2009

К сожалению, нет механизма, позволяющего делать то, что вы хотите - открытие аудиопотока предотвращает переходы состояния питания, равно как и открытие файла по сети и любые другие действия.

Это функция аудиодрайвера (portcls.sys), а не WASAPI, и это не новое поведение для Vista - я считаю, что XP и Win2K имели похожее поведение (хотя переходы между состояниями питания в Vista гораздо надежнее, чем были на XP и Win2K, поэтому пользователи, как правило, больше зависят от них).

В Windows 7 вы можете использовать «powercfg -requests», чтобы определить, не мешают ли какие-либо части системы перейти в спящий режим. Больше информации об этом можно найти здесь

2 голосов
/ 09 апреля 2009

Большое спасибо Ларри за подтверждение такого поведения, а не за то, что я делаю глупости.

Чтобы обойти эту проблему, я использовал 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
}

Участник spi.TimeRemaining ведет обратный отсчет (в секундах) от времени, указанного пользователем в панели управления, например, «Ожидание системы через 1 час» и сбрасывается всякий раз, когда загрузка процессора (в процентах) превышает spi.MaxIdlenessAllowed.

Если spi.TimeRemaining когда-либо достигнет нуля, система должна перейти в спящий режим, поэтому я закрываю все свои ручки WASAPI и позволяю это сделать.

0 голосов
/ 14 марта 2009

Я мог бы попытаться прочитать информацию о тайм-ауте энергосбережения из API управления питанием, а затем приостановить запись, если система приближается к порогу энергосбережения;

Хорошая идея, но я думаю, довольно сложно. Тайм-аут энергосбережения должен быть читаемым с помощью API управления питанием, но вам также необходимо знать текущее состояние простоя ввода пользователя, которое не читается из службы Windows.

0 голосов
/ 13 марта 2009

Я полагаю, что в API управления питанием есть функция, которая позволяет приложению сообщать ОС, что оно не хочет, чтобы система переходила в режим энергосбережения в течение некоторого времени (я думаю, что это функция типа включения / выключения). Если что-то в WASAPI вызывает этот метод, вы ничего не можете сделать. Это имело бы смысл с поведением аппаратных кнопок, поскольку служба управления питанием не обязана выполнять запрос приложения в зависимости от того, как активирован режим питания.

Что касается обхода, я не знаю. Я мог бы попытаться прочитать информацию о тайм-ауте энергосбережения из API управления питанием, а затем приостановить запись, если система приближается к порогу энергосбережения; Я понятия не имею, насколько это будет сложно. Удачи. :)

...