Приложение ломается после сна — события питания и устойчивое восстановление

· Обновлено: · · Windows, Управление питанием, Разработка под Windows, Бизнес-приложения, Управление оборудованием, Диагностика сбоев, Win32 API

История изменений (первая версия, опубликована 22 Aug 2026)
Первая публикация
Цитирование статьи(DOI (зарегистрированный архив): 10.5281/zenodo.22176747)

Приведённые ниже DOI относятся к ранее зарегистрированным архивным версиям, которые могут отличаться от текущего текста. Для ссылки на текущий текст используйте URL этой страницы.

Го Комура (2026). Приложение ломается после сна — события питания и устойчивое восстановление. KomuraSoft LLC. https://comcomponent.com/ru/blog/windows-sleep-resume-power-events/

DOI (зарегистрированный архив)
10.5281/zenodo.22176747
DOI (последняя зарегистрированная версия)
10.5281/zenodo.22176748

Закрыли ноутбук, утром открыли — бизнес-приложение в ошибках. Приложение мониторинга оборудования теряет данные только после обеда. Фоновая утилита выгрузки в Excel иногда останавливается с ошибкой соединения. При таких симптомах первым делом подозревайте поведение через сон.

Часть традиционных бизнес-приложений писали из допущения «ПК всегда включён». Теперь, когда центр повседневной работы — ноутбук, среду, которая засыпает через несколько минут бездействия, игнорировать нельзя. К тому же на машинах с Modern Standby сон устроен иначе, чем в классической модели.

Статья рассчитана на разработчиков бизнес-приложений и ПО управления оборудованием под Windows. По первичным источникам разбираем в таком порядке: уведомления, которые доставляет ОС → что ломается после пробуждения → как проектировать восстановление → как расследовать на месте.

1. Сначала выводы

Центр проекта — не «всегда успеть прибрать до сна», а «уметь восстановиться после пробуждения, когда бы машина ни остановилась». Держите в уме три пункта.

  • Предварительное уведомление не гарантирует, что вы успеете закончить. От сна отказаться нельзя, а запас на PBT_APMSUSPEND — около 2 секунд. При критической приостановке уведомление не приходит вовсе. Даже при Modern Standby нельзя считать, что настольное приложение продолжает работать во сне.123
  • Проектируйте из допущения, что соединения, дескрипторы и непрерывность времени через пробуждение не сохраняются. Ведите в ту же логику переподключения не только уведомление о пробуждении, но и ошибки обмена; пересмотрите и расписание таймеров, и разности прошедшего времени.
  • Запрет сна и готовность к пробуждению — разные меры. На нужных интервалах работы используйте SetThreadExecutionState или запрос питания и всегда снимайте его потом. Явное действие пользователя это всё равно не остановит, поэтому это не повод пропускать логику восстановления.45

Можно начать с главы, которая совпадает с вашей целью.

Что хотите узнать Какую главу читать
Какие уведомления приходят до и после сна Глава 2: цепочка событий питания
Чем отличается Modern Standby Глава 3: поведение системы и приостановка приложения
Почему возникают ошибки соединения и сдвиг времени Глава 4: классические симптомы
Как реализовать переподключение, работу со временем и запрет сна Глава 5: проект, устойчивый к пробуждению
Как разбирать обращение в поддержку Глава 6: powercfg и журнал событий

2. Что происходит вокруг сна — цепочка событий питания

ОС уведомляет приложения об изменении состояния питания сообщением WM_POWERBROADCAST.2 Сначала три события, которыми пользуются вокруг перехода в приостановку. Чем низкопотребляющий простой Modern Standby отличается — в главе 3.

Событие Смысл
PBT_APMSUSPEND Сейчас уйдёт в сон (последний шанс подготовиться)
PBT_APMRESUMEAUTOMATIC Проснулась (приходит всегда при пробуждении)
PBT_APMRESUMESUSPEND Пробуждение по действию пользователя (это условно)
Цепочка уведомлений о сне и пробужденииНепосредственно перед сном приходит PBT_APMSUSPEND с запасом около 2 секунд; при пробуждении всегда приходит PBT_APMRESUMEAUTOMATIC, а PBT_APMRESUMESUSPEND следует только если пробудил пользовательПриложениеОСПриложениеОССон (код не выполняется)PBT_APMSUSPEND (запас около 2 секунд)Сохранить состояние и закрыть соединенияPBT_APMRESUMEAUTOMATIC (приходит при пробуждении)Переподключить и заново собрать состояниеPBT_APMRESUMESUSPEND (только при пробуждении пользователем)Обновление экрана и прочая работа для пользователя

Рис. 1: Уведомления сводятся к «слову непосредственно перед и одному-двум после пробуждения». Восстановление ведёт обработка на стороне пробуждения.

Уведомление перед сном — шанс «подготовиться, если успеете»

PBT_APMSUSPEND — уведомление непосредственно перед входом в сон. Оно позволяет закрыть файлы и сохранить состояние, но приходит с двумя ограничениями.

Ограничение Влияние на проект
Запас — около 2 секунд на приложение Дальше система идёт, не дожидаясь приложения1
При критической приостановке предварительного уведомления нет Например при критически низком заряде батареи машина останавливается без подготовки2

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

Разница между обычным сном и критической приостановкойОбычный сон доставляет PBT_APMSUSPEND непосредственно перед с запасом около 2 секунд на подготовку, а критическая приостановка из-за почти севшей батареи и тому подобного останавливается без предварительного уведомления, поэтому проект, который зависит от предварительного уведомления, не держитсяОбычный сонPBT_APMSUSPEND (запас около 2 секунд)Подготовиться, затем остановитьсяКритическая приостановка (батарея почти села)Остановиться без предварительного уведомленияПроект, который предполагает, что уведомление придёт, не держится

Рис. 2: Критическая приостановка приходит без предупреждения. Поэтому подготовка — «бонус, если успеете», а суть — на стороне пробуждения.

Уведомления о пробуждении разделяют механическое восстановление и работу для пользователя

При выходе из приостановки сначала приходит PBT_APMRESUMEAUTOMATIC. Если машина проснулась из-за кнопки питания или нажатия клавиши либо присутствие пользователя обнаружили уже после пробуждения, следом идёт PBT_APMRESUMESUSPEND.67

Наоборот, при автономном пробуждении — удалённом по сети или для обслуживания — приходит только PBT_APMRESUMEAUTOMATIC. Обязательное восстановление вроде пересборки соединений делайте на первом, а действия для пользователя — обновление экрана или запрос повторного входа — на втором.6

Разделение работы по двум этапам пробужденияМеханическое восстановление вроде переподключения кладите на PBT_APMRESUMEAUTOMATIC, которое приходит при пробуждении; работу для пользователя вроде обновления экрана или запроса повторного входа — на PBT_APMRESUMESUSPEND, которое приходит только при пробуждении пользователемPBT_APMRESUMEAUTOMATIC (при пробуждении)Механическое восстановлениеPBT_APMRESUMESUSPEND (пробуждение пользователем)Работа для пользователяПереподключить и заново открыть дескрипторыОбновление экрана и запрос повторного входа

Рис. 3: Второе не приходит при автономном пробуждении, поэтому если обязательное восстановление повесить на второе, его пропустите.

Приложения без окна тоже могут получать уведомления

Службы и консольные приложения без окна могут вызвать RegisterSuspendResumeNotification с DEVICE_NOTIFY_CALLBACK и получать те же уведомления через обратный вызов.8

Кроме того, WM_POWERBROADCAST не различает, был ли низкопотребляющий режим сном или гибернацией.7 Приложение должно проектировать восстановление вокруг общего события «остановилось и вернулось».

3. Modern Standby — смысл «сна» изменился

То, что система работает, и то, что приложение может работать, — разные вещи

Классический сон S3 — модель, которая останавливает систему целиком. Modern Standby, напротив, похож на смартфон: после выключения экрана система продолжает работать прерывисто.

Однако это не значит, что обычные настольные приложения продолжают работать. На первом этапе входа в сон их приостанавливает Desktop Activity Moderator (DAM).3

Режим Поведение системы Допущение для настольных приложений
Классический сон S3 Останавливается вся система Код во сне не выполняется
Modern Standby Работает прерывисто, чтобы держать сеть, принимать уведомления и так далее Приостановлены DAM; обычный код не выполняется

От прерывистой активности выигрывают компоненты, построенные под этот механизм. Для проекта бизнес-приложения вывод в обоих случаях один: «свой код во сне не выполняется».3

Разница между классическим сном и Modern StandbyКлассический сон S3 останавливает всю систему, а при Modern Standby система продолжает работать прерывисто после выключения экрана. Настольные приложения, однако, приостанавливает DAM, поэтому код приложения не выполняется ни в том ни в другом случаеКлассический сон S3: останавливается вся системаКод приложения не выполняетсяModern Standby: система работает прерывистоНастольные приложения приостанавливает DAM

Рис. 4: Модель изменилась, но для настольного приложения вывод тот же: «во сне работать нельзя».

Не делайте уведомление о пробуждении единственным пусковым механизмом восстановления

Вход и выход из низкопотребляющего простоя Modern Standby не всегда совпадают с классическим переходом в приостановку. Соединение может быть уже разорвано, а уведомление так и не пришло. Считайте уведомление о пробуждении вспомогательным средством, которое ускоряет восстановление, а в центр кладите путь, который переподключает при обнаружении ошибки обмена. Конкретную структуру разбирает глава 5.

Кроме того, переход в низкопотребляющее состояние идёт постепенно, поэтому момент обрыва и остановки не такой резкий, как при S3. Пользователям тоже трудно отличить «просто погас экран» от «уснула», поэтому при сборе симптомов подтверждайте закрывали ли крышку и сколько минут машина простояла без действия.

4. Что ломается — классические симптомы

Ошибки после пробуждения удобно разложить на соединения, дескрипторы устройств и непрерывность времени. Для общих ресурсов ещё проверьте, сколько занимают повторная аутентификация и повторное установление сети.

TCP-соединение не замечает обрыв, пока вы не отправите или не примете

Во время сна удалённая сторона, устройства NAT и файрволы воспринимают ваше молчание как тайм-аут и отбрасывают соединение. Ваш сокет об этом ничего не знает, поэтому ошибка возникает только когда вы отправляете или принимаете после пробуждения.

Иногда ожидающий приём вообще не даёт ошибки. Поэтому нужен keepalive, который проверяет, живо ли соединение. Соединения с базами данных и WebSocket следуют той же схеме.

Последовательные порты и USB-устройства нужно открывать заново

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

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

Периодическую работу, прошедшее время и работу по расписанию разбирайте отдельно

Проблемы со временем делятся на три вида.

Работа Что происходит через сон Мера
Периодическая вроде «опрашивать каждые 10 секунд» Во сне останавливается. Как срабатывает после пробуждения, зависит от API и среды выполнения Заново выстроить расписание при пробуждении
Расчёты по разности с предыдущей меткой времени Разность внезапно становится «на 8 часов», и ломаются средние или суждения о тайм-ауте Защититься от аномально больших разностей
Работа по расписанию вроде «каждую ночь в 2:00» Не выполняется, если ПК в это время спит При необходимости используйте пробуждение Планировщика заданий

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

Три формы, в которых ломается непрерывность времениПериодическая работа во сне останавливается, а срабатывание после пробуждения зависит от API, поэтому заново выстраивайте расписание при пробуждении; разность с предыдущей меткой времени после пробуждения становится огромной, поэтому защищайте её; работа по расписанию не выполняется, если машина спит, поэтому рассмотрите пробуждение Планировщика заданийПериодическая работа: во сне останавливаетсяЗаново выстроить расписание при пробужденииРазность прошедшего времени: взрываетсяЗащититься от аномальных разностейРабота по расписанию: спала, так и не выполниласьРазбудить машину настройкой пробуждения

Рис. 5: Обработку таймеров и часов пишите из допущения, что «время прыгает». У каждой из трёх форм свой тип меры.

Три вещи, которые ломаются через сонЧерез сон TCP-соединение отбрасывается по тайм-ауту на стороне партнёра, дескриптор USB-устройства становится недействительным как при повторном подключении, а работа по прошедшему времени видит огромный скачок времени. Восстанавливайте каждое переподключением, повторным открытием и защитой разностиИнтервал снаTCP-соединение: отброшено партнёромUSB-устройство: дескриптор недействителенПрошедшее время: огромный скачокОбнаружить ошибку и переподключитьЗаново открыть устройствоЗащититься от аномальных разностей

Рис. 6: То, что ломается, делится на три семейства — «соединения», «дескрипторы» и «непрерывность времени», — и у каждого есть устоявшийся тип восстановления.

Сетевые диски и VPN сразу после пробуждения имеют период ожидания

Сетевым дискам и VPN после пробуждения иногда нужна повторная аутентификация и повторное установление. В результате сразу после пробуждения есть окно в несколько секунд или десятков секунд, в котором доступ не проходит.

Вместо того чтобы повторять всё сразу в момент пробуждения, проектируйте так, чтобы немного подождать и повторять поэтапно.

5. Как строить приложения, которые переживают пробуждение

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

Сведите уведомление о пробуждении и ошибки обмена в одну логику переподключения

Когда WM_POWERBROADCAST окна верхнего уровня получает PBT_APMRESUMEAUTOMATIC, отбросьте удерживаемые соединения и соберите их заново. Однако не полагайтесь только на уведомление о пробуждении. Уведомления можно пропустить, и обмен может произойти раньше, чем придёт уведомление.

Всегда давайте путь «переподключить, когда обнаружена ошибка обмена», а уведомление о пробуждении считайте триггером, который запускает эту работу раньше. Следующий пример на C# — часть, которая запрашивает переподключение из уведомления о пробуждении. Сторона ошибки обмена сводится в ту же логику переподключения.

// C#: свести и уведомление о пробуждении, и ошибки обмена в одну логику переподключения
protected override void WndProc(ref Message m)
{
    const int WM_POWERBROADCAST = 0x0218;
    const int PBT_APMRESUMEAUTOMATIC = 0x0012;
    if (m.Msg == WM_POWERBROADCAST && (int)m.WParam == PBT_APMRESUMEAUTOMATIC)
    {
        _connectionManager.RequestReconnect();   // идемпотентный запрос на переподключение
    }
    base.WndProc(ref m);
}

Переподключение сочетает «идемпотентность, backoff и keepalive»

Логике переподключения нужны следующие три элемента вместе.

Элемент Роль
Идемпотентное переподключение Безопасно восстановиться, сколько бы раз его ни запросили
Повторы с экспоненциальной задержкой Удлинять интервал до следующей попытки после сбоя
Keepalive в установившемся состоянии Подтверждать, что соединение живо, и рано обнаруживать обрыв

Этот набор из трёх частей помогает не только при пробуждении ото сна, но и как есть — при коротких обрывах сети и перезапусках устройства.

Проект переподключения, устойчивый к пробуждениюУведомление о пробуждении, ошибка обмена и сбой keepalive сводятся в одну идемпотентную логику переподключения, которая при сбое повторяет с экспоненциальной задержкойДаНетУведомление о пробуждении (PBT_APMRESUMEAUTOMATIC)Идемпотентная логика переподключенияОбнаружена ошибка обменаСбой keepaliveУдалось?Вернуться к обычной работеПовторить после экспоненциальной задержки

Рис. 7: Соберите переподключение в один идемпотентный путь и входите на ту же дорогу из уведомления о пробуждении, обнаружения ошибки или keepalive.

Не смешивайте в расчёты интервал, где время прыгнуло

В работе, которая использует «прошедшее время с прошлого раза», добавьте защиту, которая признаёт интервал недействительным, когда обнаруживает аномально большую разность. Суть — не складывать её в среднее и не трактовать как обычный тайм-аут.

Когда измеряете время через пробуждение, отличайте часы, которые продолжают идти во сне (настенное время), от времени, реально потраченного на работу. Заново выстроить расписание периодической работы и обработать работу по расписанию, которая не выполнилась, тоже стоит пересмотреть по категориям главы 4.

Участки, которые нельзя прерывать, явно запрещайте сну

Пока идёт работа, которую нельзя усыпить, — миграция данных или непрерывный обмен с устройством, — используйте SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED). Если нужно ещё держать дисплей включённым, добавьте ES_DISPLAY_REQUIRED.74

Другое средство — запрос питания через PowerCreateRequest и PowerSetRequest. К нему можно прикрепить строку причины, поэтому powercfg /requests показывает «кто мешает сну и почему». Этот вариант добрее тем, что эксплуатация может прочитать причину.5

Средство Единица управления и оговорки
SetThreadExecutionState На поток. Снимайте с того же потока, который установил
Запрос питания (PowerCreateRequest + PowerSetRequest) Управляется дескриптором. Берите его для работы, которая меняет потоки, например async/await

Однако установка запрета не предотвращает всякое прерывание. Следующие ограничения проверяйте отдельно от логики восстановления.

Ограничение Необходимый ответ
Запрещается автоматический сон по бездействию Оставляйте логику переподключения для явных действий вроде закрытия крышки или выбора «Сон» в меню «Пуск»
На машине с Modern Standby от батареи запросы питания тоже срезаются спустя некоторое время после тайм-аута сна Непрерывную работу гарантируйте питанием от сети или на стороне эксплуатации5
Пропущенное снятие не даёт ПК уснуть Всегда снимайте, когда работа закончена
Два средства запретить сонПользуетесь ли вы удобным SetThreadExecutionState или API запроса питания, к которому можно прикрепить строку причины и который администратор видит через powercfg, всегда снимайте его, когда работа заканчиваетсяИнтервал работы, который нельзя усыпитьSetThreadExecutionStateЗапрос питания (PowerSetRequest)Удобно, только флагиС причиной, видно в powercfgВсегда снимать, когда работа закончена

Рис. 8: При любом средстве «снять, когда закончили» — абсолютное условие. Запрос питания, который может сделать причину видимой, добрее к эксплуатации.

Если непрерывная работа — требование, пересмотрите размещение и эксплуатацию

Службы и приложения без окна тоже могут получать уведомления через DEVICE_NOTIFY_CALLBACK у RegisterSuspendResumeNotification.8

Если непрерывная работа действительно нужна, однако, пересмотрите, стоит ли держать работу резидентно на клиентском ПК, который вообще засыпает. Перенести работу на сторону сервера или на машину, которую эксплуатируют без сна — фундаментальное исправление.

6. Расследование — powercfg и журнал событий

По обращению в поддержку сначала подтвердите, спала ли машина непосредственно перед ошибкой. Спросите, закрывали ли крышку и сколько минут машина простояла без действия, затем берите инструмент под симптом.

Что выяснить Инструмент Что смотреть
Почему не засыпает powercfg /requests Процессы и драйверы, держащие запросы питания. Также проверьте SetThreadExecutionState, который так и не сняли
Почему просыпается сам powercfg /lastwake, powercfg /waketimers Причина последнего пробуждения и таймеры, зарезервированные на пробуждение
Качество Modern Standby powercfg /sleepstudy Потребление и активность на каждый интервал сна9
Шкала времени сна и пробуждения Kernel-Power в журнале «Система» Записи входа в сон и пробуждения

Сопоставление журнала событий с журналом приложения позволяет объективно подтвердить, было ли пробуждение непосредственно перед ошибкой. Не останавливайтесь на подозрении сна: выстройте метки времени и локализуйте причину.

Соответствие симптомов проблем с питанием командам расследованияПри симптоме «не засыпает» найдите, кто держит запрос питания, через powercfg /requests; при симптоме «просыпается сам» найдите причину пробуждения через /lastwake и /waketimers; для шкалы времени используйте Kernel-Power в журнале событийНе засыпаетpowercfg /requestsПросыпается самpowercfg /lastwake и /waketimersХотите проверить шкалу времениKernel-Power в журнале событийНеснятый запрет сна тоже видно

Рис. 9: Симптомы отображаются на команды расследования тремя семействами. Сначала подтвердите «спала ли непосредственно перед», затем выбирайте инструмент.

7. Итог

Обработка сна не заканчивается тем, что вы получили уведомления. Заложите, что подготовка может не успеть и что уведомление о пробуждении может не прийти, и разделите роли так.

Цель проекта или расследования На что опираться
Перед сном Отказаться нельзя. Готовьтесь в запасе около 2 секунд у PBT_APMSUSPEND, но при критической ситуации уведомления нет
Уведомления о пробуждении Обязательное восстановление на PBT_APMRESUMEAUTOMATIC, работа для пользователя на PBT_APMRESUMESUSPEND. Не полагайтесь только на уведомления
Соединения и дескрипторы Центр — переподключение по ошибкам обмена; сочетайте идемпотентность, экспоненциальную задержку и keepalive
Время Защищайтесь от аномальных разностей прошедшего времени и заново выстраивайте периодическую работу. Работа по расписанию во сне не выполняется
Запрет сна Ставьте только на нужных интервалах и снимайте потом. Оставляйте восстановление для явных действий сна и тому подобного
Расследование причин Спросите, спала ли машина непосредственно перед, и сопоставьте записи powercfg и Kernel-Power с журналом приложения

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

Похожие статьи

Смежные области консультирования

KomuraSoft LLC занимается расследованием причин проблем вроде «после пробуждения ото сна обрывается обмен» и «соединение с устройством падает после обеда», доработкой логики переподключения и обработки событий питания в существующих приложениях и ревью проекта бизнес-приложений и ПО управления оборудованием, рассчитанных на работу с ноутбука.

Справочные ссылки

  1. Microsoft Learn, PBT_APMSUSPEND event. О том, что это событие доставляется непосредственно перед тем, как компьютер входит в состояние приостановки; о том, что от приложения ожидают завершить работу, нужную для сохранения данных; и о том, что система даёт около 2 секунд на обработку этого уведомления, а приложение, которое продолжает обработку дольше, может быть прервано. ↩ ↩2

  2. Microsoft Learn, System Power Management Events. О том, что система заранее рассылает изменения режима работы вроде сна; о том, что PBT_APMSUSPEND доставляется перед сном по бездействию, чтобы приложение могло подготовиться, закрыв файлы и сохранив данные; о том, что при критической приостановке (критически низкий заряд батареи и тому подобное) предварительного уведомления нет; о том, что каждому приложению на обработку этого сообщения дают не больше 2 секунд и после тайм-аута его прерывают; и о том, что при пробуждении уведомляется каждое приложение. ↩ ↩2 ↩3

  3. Microsoft Learn, Prepare software for modern standby. О том, что Desktop Activity Moderator (DAM) приостанавливает настольные приложения на первом этапе перехода в Modern Standby; и о том, что система затем поэтапно переходит в низкопотребляющую фазу и фазу устойчивости, а прерывисто работают только разрешённые компоненты. ↩ ↩2 ↩3

  4. Microsoft Learn, SetThreadExecutionState function (winbase.h). О том, что ES_SYSTEM_REQUIRED и ES_DISPLAY_REQUIRED подавляют автоматический сон системы и выключение дисплея; и о том, что непрерывный запрет объявляют через ES_CONTINUOUS и снимают, закончив, вызовом с одним только ES_CONTINUOUS. ↩ ↩2

  5. Microsoft Learn, PowerSetRequest function (winbase.h). О том, что для объекта запроса питания, созданного через PowerCreateRequest, задают типы вроде «держать систему или дисплей включёнными»; о прикреплении диагностической строки причины; и о том, что неснятые запросы питания можно перечислить через powercfg /requests. ↩ ↩2 ↩3

  6. Microsoft Learn, PBT_APMRESUMESUSPEND event. О том, что это отправляется после PBT_APMRESUMEAUTOMATIC при пробуждении пользователем или когда ввод пользователя обнаруживают позже; о том, что при пробуждении по внешней причине вроде удалённого пробуждения отправляется только PBT_APMRESUMEAUTOMATIC; и о том, что от приложения ожидают заново открыть файлы, закрытые перед сном, и подготовиться к вводу пользователя. ↩ ↩2

  7. Microsoft Learn, WM_POWERBROADCAST message. О том, что PBT_APMRESUMEAUTOMATIC всегда отправляется при пробуждении, а PBT_APMRESUMESUSPEND дополнительно — при пробуждении от ввода пользователя; о том, что это сообщение не различает вид низкопотребляющего состояния; о том, что подробности переходов состояния питания пишутся в журнал событий «Система»; и о вызове SetThreadExecutionState, чтобы система не входила в низкопотребляющее состояние. ↩ ↩2 ↩3

  8. Microsoft Learn, RegisterSuspendResumeNotification function (winuser.h). О том, что это API регистрации на уведомления о приостановке и пробуждении, и о том, что указание DEVICE_NOTIFY_CALLBACK позволяет кроме доставки сообщения дескриптору окна получать уведомления через обратный вызов в приложении или службе без окна. ↩ ↩2

  9. Microsoft Learn, Modern standby SleepStudy. О том, что отчёт, который даёт powercfg /sleepstudy, показывает на каждый интервал Modern Standby потребление, активность и причину пробуждения (кнопка питания, ввод пользователя, таймер пробуждения и так далее). ↩

Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.

Эти страницы показывают тему статьи в более широком контексте услуг и решений.

Статья напрямую связана со следующими услугами.

Частые вопросы

Вопросы, которые часто возникают при консультациях по теме статьи.

Может ли приложение заранее узнать о сне и отказаться от него?
В актуальных версиях Windows уведомление получить можно, отказаться от сна — нет. Непосредственно перед сном сообщение WM_POWERBROADCAST доставляет событие PBT_APMSUSPEND: здесь можно закрыть файлы и сохранить состояние. Но на обработку отводится около двух секунд на приложение; если не уложиться, система идёт дальше, не дожидаясь. При критической приостановке, например когда батарея на исходе, предварительного уведомления нет вовсе. Поэтому схема «обязательно успеть до сна» не работает: нужна схема, которая умеет восстановиться при пробуждении, когда бы ни оборвалась работа. Участок, который действительно нельзя усыпить, явно блокируйте через SetThreadExecutionState или запрос питания (PowerSetRequest).
Как узнать, что машина проснулась?
Если у приложения есть окно, обрабатывайте WM_POWERBROADCAST. При выходе из приостановки приходит PBT_APMRESUMEAUTOMATIC; если пробуждение вызвал пользователь (кнопка питания или нажатие клавиши), следом идёт PBT_APMRESUMESUSPEND. Если машина проснулась без пользователя и сразу снова засыпает, приходит только PBT_APMRESUMEAUTOMATIC. Поэтому обязательную работу вроде переподключения вешайте на PBT_APMRESUMEAUTOMATIC, а обращённую к пользователю — обновление экрана и тому подобное — на PBT_APMRESUMESUSPEND. Службы и консольные приложения без окна получают те же уведомления через обратный вызов, если вызвать RegisterSuspendResumeNotification с DEVICE_NOTIFY_CALLBACK.
Можно ли продолжать выполнять приложение во время сна?
Как правило, нет. Во время сна выполнение на CPU останавливается (на устройстве с Modern Standby настольные приложения приостанавливает Desktop Activity Moderator), и код приложения не идёт. Есть два пути. Первый — запрещать сон только на время работы. Флаг ES_SYSTEM_REQUIRED через SetThreadExecutionState или запрос питания через PowerCreateRequest/PowerSetRequest на этот интервал блокирует автоматический сон по бездействию (проверить можно через powercfg /requests). Явное действие пользователя, например закрытие крышки, это всё равно не остановит, поэтому к пробуждению нужно быть готовым даже при активном запрете. Второй — принять сон и проектировать так, чтобы «наверстать после пробуждения». Для работы по расписанию вроде ночного пакетного задания ПК можно ещё будить опцией Планировщика заданий «Выводить компьютер из спящего режима для выполнения задачи». Работа, которой действительно нужно идти непрерывно, должна жить на сервере или в службе, настроенной так, чтобы не засыпать.
Почему после пробуждения перестают работать TCP-соединения и последовательные порты?
Потому что сетевые адаптеры и USB-устройства во время сна тоже уходят в режим пониженного потребления. TCP-соединение уже сброшено удалённой стороной или по тайм-ауту NAT либо файрвола, и отправка или приём после пробуждения возвращает ошибку (часто вы замечаете это только когда ошибка уже случилась). USB-преобразователи последовательного порта и подобные при пробуждении иногда трактуются как извлечение и повторное подключение устройства, и открытый дескриптор становится недействительным. Для обоих правильное допущение — «дескрипторы и соединения не переживают пробуждение», а правильный ответ — логика переподключения, которая заново устанавливает соединение по уведомлению о пробуждении или по ошибке обмена. Устоявшийся приём — периодический keepalive плюс повтор с экспоненциальной задержкой при сбое.
Как разбирать самопроизвольный сон и самопроизвольное пробуждение?
Первый инструмент — команда powercfg. Если «не засыпает», powercfg /requests показывает, какие процессы и драйверы держат запрос питания и мешают сну. Если «просыпается сам», powercfg /lastwake показывает причину последнего пробуждения, а powercfg /waketimers — таймеры, которые сейчас зарезервированы на пробуждение. На устройстве с Modern Standby powercfg /sleepstudy даёт отчёт о потреблении и активности во время сна. История сна и пробуждения также пишется в журнал событий (источник Kernel-Power в журнале «Система»), так что по шкале времени можно увидеть, когда машина уснула и когда и почему проснулась.

Об авторе

Страница с профилем автора статьи.

Го Комура

Представитель KomuraSoft LLC

Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.

Публичные ссылки

Вернуться в блог