Apps That Break on Resume from Sleep — How Power Events Work and How to Build Business Apps That Survive Resume
· Updated: · Go Komura · Windows, Power Management, Windows Development, Business Applications, Device Control, Bug Investigation, Win32 API
Revision history (1 updates, last updated Sep 8, 2026)
A log of the changes made to this article. Where a pre-update version was archived, it stays readable at a permanent DOI link.
- Retranslated as a full translation of the current Japanese original. The previous English version was an abridgement that dropped subsections, tables, diagrams, and paragraphs; all of them have been restored to match the Japanese article, and the knowledge map section has been added where the Japanese article has one. The technical claims are the same as in the Japanese version. Read the version before this update (DOI: 10.5281/zenodo.22170905)
- First published
Cite this article(DOI: 10.5281/zenodo.22170904)
This article is archived on Zenodo. Below are both the DOI that always resolves to the latest version and the DOI pinned to the version you are reading.
Go Komura (2026). Apps That Break on Resume from Sleep — How Power Events Work and How to Build Business Apps That Survive Resume. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22170904 https://comcomponent.com/en/blog/windows-sleep-resume-power-events/
- DOI (latest version)
- 10.5281/zenodo.22170904
- DOI (this version)
- 10.5281/zenodo.22652525
You close the laptop, open it the next morning, and the business app is full of errors. An equipment-monitoring app drops data only after the lunch break. A resident tool that exports to Excel occasionally stops on a connection error. With symptoms like these, the first thing to suspect is behavior across sleep.
Some traditional business apps were written on the assumption that “the PC stays on”. Now that laptops have become the center of daily work, an environment that sleeps within minutes if left alone cannot be ignored. On top of that, machines that support Modern Standby sleep by a different mechanism than the traditional one.
This article is for developers building business apps and device-control software on Windows. It lays out, from primary sources, the notifications the OS delivers, what breaks after resume, how to design recovery, and how to investigate in the field, in that order.
1. The Bottom Line First
The center of the design is not “always clean up before sleep” but “be able to recover after resume no matter when the machine stops”. There are three points to keep in mind.
- The advance notification is no guarantee that you can finish. Sleep cannot be refused, and the grace period for
PBT_APMSUSPENDis about 2 seconds. On an emergency suspend the notification does not arrive at all. Even under Modern Standby, you cannot assume a desktop app keeps running during sleep.123 - Design on the assumption that connections, handles, and the continuity of time are not preserved across resume. Route communication errors, not only the resume notification, into the same reconnect logic, and revisit timer schedules and elapsed-time differences as well.
- Sleep suppression and preparing for resume are separate measures. Use
SetThreadExecutionStateor a power request for the work intervals that need it, and always clear it afterward. It cannot prevent an explicit sleep action by the user, though, so it is no reason to skip the recovery logic.45
You can also start from the chapter that matches your goal.
| What you want to know | Chapter to read |
|---|---|
| Which notifications arrive before and after sleep | Chapter 2: The flow of power events |
| What is different under Modern Standby | Chapter 3: System behavior and app suspension |
| Why connection errors and time skew happen | Chapter 4: Classic symptoms |
| How to implement reconnection, time handling, and sleep suppression | Chapter 5: Resume-resilient design |
| How to triage a support ticket | Chapter 6: powercfg and the event log |
2. What Happens Around Sleep — The Flow of Power Events
The OS notifies apps of power-state changes through the WM_POWERBROADCAST message.2 First, the three events used around the suspend transition. How Modern Standby’s low-power idle differs is covered in Chapter 3.
| Event | Meaning |
|---|---|
| PBT_APMSUSPEND | About to enter sleep (the last chance to prepare) |
| PBT_APMRESUMEAUTOMATIC | Resumed (always arrives on resume) |
| PBT_APMRESUMESUSPEND | Resume caused by a user action (this one is conditional) |
sequenceDiagram
accTitle: Notification flow for sleep and resume
accDescr: PBT_APMSUSPEND arrives just before sleep with about 2 seconds of grace; on resume, PBT_APMRESUMEAUTOMATIC always arrives, and PBT_APMRESUMESUSPEND follows only for a user-initiated resume
participant OS as OS
participant A as App
OS->>A: PBT_APMSUSPEND (about 2 seconds of grace)
A->>A: Save state and close connections
Note over OS: Sleep (code does not run)
OS->>A: PBT_APMRESUMEAUTOMATIC (arrives on resume)
A->>A: Reconnect and rebuild state
OS->>A: PBT_APMRESUMESUSPEND (user-initiated resume only)
A->>A: Screen updates and other user-facing work
Figure 1: The notifications amount to “a word just beforehand, and a word or two after resume”. The resume-side handling is what drives recovery.
The Pre-Sleep Notification Is a Chance to “Prepare If There Is Time”
PBT_APMSUSPEND is the notification delivered just before entering sleep. It lets you close files and save state, but it comes with the following two constraints.
| Constraint | Effect on the design |
|---|---|
| The grace period is about 2 seconds per app | Beyond that time, the system proceeds without waiting for the app1 |
| An emergency suspend gives no advance notification | When the battery level is critical, for example, the machine stops without any preparation2 |
Therefore, a design that “always finishes saving after receiving this notification” does not hold. Use the advance notification to prepare what you can in time, and put the substance of recovery on the resume side.
flowchart TB
accTitle: Difference between ordinary sleep and emergency suspend
accDescr: Ordinary sleep delivers PBT_APMSUSPEND just beforehand with about 2 seconds to prepare, but an emergency suspend caused by a critical battery or the like stops with no advance notification, so a design that depends on the advance notification does not hold
n2["Ordinary sleep"] --> pre["PBT_APMSUSPEND (about 2 seconds of grace)"]
pre --> s1["Prepare, then stop"]
e2["Emergency suspend (battery nearly exhausted)"] --> s2["Stop with no advance notification"]
s2 -.-> l2["A design that assumes the notification will come does not hold"]
Figure 2: An emergency suspend comes with no warning. So preparation is “a bonus if it makes it in time”, and the substance goes on the resume side.
Resume Notifications Separate Mechanical Recovery from User-Facing Work
On resume from suspend, PBT_APMRESUMEAUTOMATIC arrives first. If the machine resumed because of the power button or a key press, or if user presence was detected after resume, PBT_APMRESUMESUSPEND follows.67
By contrast, on an unattended resume such as a remote wake over the network or a resume for maintenance, only PBT_APMRESUMEAUTOMATIC arrives. Do required recovery such as rebuilding connections on the former, and user-facing actions such as screen updates or a re-login prompt on the latter.6
flowchart TB
accTitle: Splitting work across the two resume stages
accDescr: Put mechanical recovery such as reconnecting on PBT_APMRESUMEAUTOMATIC, which arrives on resume; put user-facing work such as screen updates or a re-login prompt on PBT_APMRESUMESUSPEND, which arrives only on a user-initiated resume
ra["PBT_APMRESUMEAUTOMATIC (on resume)"] --> m["Mechanical recovery"]
rs["PBT_APMRESUMESUSPEND (user-initiated resume)"] --> u["User-facing work"]
m -.-> m1["Reconnect and reopen handles"]
u -.-> u1["Screen updates and a re-login prompt"]
Figure 3: The latter does not arrive on an unattended resume, so putting required recovery on the latter will miss it.
Apps Without a Window Can Receive the Notifications Too
Windowless services and console apps can use RegisterSuspendResumeNotification with DEVICE_NOTIFY_CALLBACK and receive the same notifications through a callback.8
Also, WM_POWERBROADCAST cannot tell you whether the low-power state was sleep or hibernation.7 The app should design its recovery around the common event “it stopped, and it came back”.
3. Modern Standby — The Meaning of “Sleep” Has Changed
The System Running and the App Being Able to Run Are Different Things
Traditional S3 sleep is a model that stops the whole system. Modern Standby, by contrast, is a smartphone-like model in which the system keeps running intermittently after the screen goes off.
However, that does not mean ordinary desktop apps keep running. At the first stage of entering sleep, they are paused by the Desktop Activity Moderator (DAM).3
| Mode | System behavior | Assumption for desktop apps |
|---|---|---|
| Traditional S3 sleep | The whole system stops | Code does not run during sleep |
| Modern Standby | Runs intermittently to maintain the network, receive notifications, and so on | Paused by DAM; ordinary code does not run |
The components that benefit from the intermittent activity are the ones built for this mechanism. For the design of a business app, the conclusion is the same in both cases: “your own code does not run during sleep”.3
flowchart TB
accTitle: Difference between traditional sleep and Modern Standby
accDescr: Traditional S3 sleep stops the whole system, while under Modern Standby the system keeps running intermittently after the screen goes off. Desktop apps are paused by DAM, however, so the app's code does not run in either case
s3["Traditional S3 sleep: the whole system stops"] --> conc["The app's code does not run"]
ms["Modern Standby: the system runs intermittently"] --> dam["Desktop apps are paused by DAM"]
dam --> conc
Figure 4: The model has changed, but for a desktop app the conclusion is the same: “you cannot run during sleep”.
Do Not Make the Resume Notification the Only Trigger for Recovery
Entering and leaving Modern Standby’s low-power idle does not always coincide with the traditional suspend transition. A connection can already be broken without any notification arriving. Treat the resume notification as an aid that speeds up recovery, and put a path that reconnects on detecting a communication error at the center. The concrete structure is explained in Chapter 5.
Also, because the transition into the low-power state is gradual, the timing of disconnects and stops is not as sharp as under S3. Users, too, have trouble telling “the screen just went off” from “it went to sleep”, so when you take a symptom report, confirm whether the lid was closed and how many minutes the machine was left idle.
4. What Breaks — Classic Symptoms
Errors after resume can be organized into connections, device handles, and the continuity of time. For shared resources, also check how long re-authentication and re-establishing the network take.
A TCP Connection Does Not Notice the Disconnect Until You Send or Receive
During sleep, the peer, NAT devices, and firewalls treat your silence as a timeout and discard the connection. Your socket knows nothing about it, however, so it fails only when you send or receive after resume.
Sometimes a pending receive never errors at all. That is why you need a keepalive to check whether the connection is alive. Database connections and WebSockets follow the same pattern.
Serial Ports and USB Devices Need Their Handles Reopened
A USB device can look, on resume, as if it were unplugged and plugged back in, and the handle that was open starts returning errors. This is the typical pattern behind a device-control app that “gets a communication error only after the lunch break”.
Rather than assuming the handle stays usable, structure the app so it can reopen the device. Reconnect design is also covered in the serial communication article.
Review Periodic Work, Elapsed Time, and Scheduled Work Separately
Time-related problems fall into the following three kinds.
| Work | What happens across sleep | Countermeasure |
|---|---|---|
| Periodic work such as “poll every 10 seconds” | Stops during sleep. How it fires after resume depends on the API and the runtime | Rebuild the schedule on resume |
| Calculations that use the difference from the previous timestamp | The difference suddenly becomes “8 hours’ worth”, and averages or timeout judgments break | Guard against abnormally large differences |
| Scheduled work such as “run every night at 2 AM” | Does not run if the PC is asleep at that time | Use Task Scheduler’s wake-from-sleep feature if needed |
Periodic work in particular may fire once immediately after resume for the overdue tick, or nothing may happen until the next period. Do not leave the handling of missed runs to the implicit behavior of the timer.
flowchart TB
accTitle: Three shapes in which the continuity of time breaks
accDescr: Periodic work stops during sleep and post-resume firing differs by API, so rebuild the schedule on resume; the difference from the previous timestamp becomes huge after resume, so guard it; scheduled work does not run if the machine is asleep, so consider Task Scheduler's wake-from-sleep
t1["Periodic work: stops during sleep"] -.-> g1["Rebuild the schedule on resume"]
t2["Elapsed-time difference: blows up"] -.-> g2["Guard against abnormal differences"]
t3["Scheduled work: asleep, never ran"] -.-> g3["Wake the machine with a wake setting"]
Figure 5: Write timer and clock handling on the assumption that “time jumps”. Each of the three shapes has its own type of countermeasure.
flowchart TB
accTitle: Three things that break across sleep
accDescr: Across sleep, a TCP connection is discarded by a timeout on the peer side, a USB device's handle is invalidated as if reconnected, and elapsed-time-based work observes a huge time jump. Recover each with reconnect, reopen, and a difference guard
sleep["Sleep interval"] --> tcp["TCP connection: discarded by the peer"]
sleep --> usb["USB device: handle invalidated"]
sleep --> time["Elapsed time: a huge jump"]
tcp -.-> r1["Detect the error and reconnect"]
usb -.-> r2["Reopen the device"]
time -.-> r3["Guard against abnormal differences"]
Figure 6: What breaks falls into three families, “connections”, “handles”, and “continuity of time”, and each has a settled type of recovery.
Network Drives and VPNs Have a Waiting Period Right After Resume
Network drives and VPNs sometimes need re-authentication and re-establishment after resume. As a result, there is a window of a few seconds to a few tens of seconds right after resume in which access fails.
Rather than retrying everything at once the moment the machine resumes, design the app to wait a little and retry in stages.
5. Building Apps That Survive Resume
The principle is to structure the app so it can recover at any time, even though connections and handles do not survive across sleep. Design reconnection, time handling, and sleep suppression for the intervals that need it, each on its own.
Funnel the Resume Notification and Communication Errors into the Same Reconnect Logic
When the top-level window’s WM_POWERBROADCAST receives PBT_APMRESUMEAUTOMATIC, discard the connections you hold and rebuild them. However, do not rely on the resume notification alone. Notifications can be missed, and communication can happen before the notification arrives.
Always provide a path that “reconnects when a communication error is detected”, and treat the resume notification as a trigger that starts that work earlier. The following C# example is the part that requests a reconnect from the resume notification. The communication-error side funnels into the same reconnect logic.
// C#: funnel both the resume notification and communication errors into the same reconnect logic
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(); // idempotent reconnect request
}
base.WndProc(ref m);
}
Reconnection Combines “Idempotence, Backoff, and Keepalive”
Reconnect logic needs the following three elements together.
| Element | Role |
|---|---|
| Idempotent reconnection | Recover safely no matter how many times it is requested |
| Retries with exponential backoff | Lengthen the interval before the next attempt after a failure |
| Keepalive in the steady state | Confirm the connection is alive and detect a disconnect early |
This three-piece set helps not only with resume from sleep but also, as is, with brief network drops and device restarts.
flowchart TB
accTitle: Resume-resilient reconnect design
accDescr: The resume notification, a communication error, and a keepalive failure all funnel into the same idempotent reconnect logic, which retries with exponential backoff on failure
e1["Resume notification (PBT_APMRESUMEAUTOMATIC)"] --> r["Idempotent reconnect logic"]
e2["Communication error detected"] --> r
e3["Keepalive failure"] --> r
r --> ok{"Succeeded?"}
ok -->|"Yes"| run["Back to normal operation"]
ok -->|"No"| back["Retry after exponential backoff"]
back --> r
Figure 7: Consolidate reconnection into a single idempotent path, and enter the same road from the resume notification, error detection, or the keepalive.
Do Not Mix an Interval Where Time Jumped into Your Calculations
In work that uses “elapsed time since last time”, add a guard that invalidates the interval when it detects an abnormally large difference. The point is not to fold it into an average and not to treat it as an ordinary timeout.
When measuring time across resume, distinguish the clock that keeps advancing during sleep (wall-clock time) from the time actually spent on work. Rebuilding the schedule of periodic work and handling scheduled work that did not run should also be reviewed using the categories in Chapter 4.
Suppress Sleep Explicitly for Work That Must Not Be Interrupted
While work that must not be slept through is in progress, such as a data migration or continuous communication with a device, use SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED). If you also want to keep the display on, add ES_DISPLAY_REQUIRED.74
The other means is a power request through PowerCreateRequest and PowerSetRequest. Because you can attach a reason string, powercfg /requests shows “who is blocking sleep, and why”. This one is kinder in that operations staff can read the reason.5
| Means | Unit of management and cautions |
|---|---|
SetThreadExecutionState |
Per thread. Clear it from the same thread that set it |
Power request (PowerCreateRequest + PowerSetRequest) |
Managed by a handle. Use this for work that changes threads, such as async/await |
However, setting suppression does not prevent every kind of interruption. Check the following constraints separately from the recovery logic.
| Constraint | Required response |
|---|---|
| What is suppressed is automatic idle sleep | Keep the reconnect logic to handle explicit actions such as closing the lid or choosing Sleep from the Start menu |
| On a Modern Standby machine running on battery, power requests are also cut off some time after the sleep timeout | Guarantee uninterruptible work with AC power or on the operations side5 |
| A missed clear makes the PC unable to sleep | Always clear it when the work finishes |
flowchart TB
accTitle: Two means of suppressing sleep
accDescr: Whether you use the convenient SetThreadExecutionState or the power request API that can attach a reason string and is visible to an administrator through powercfg, always clear it when the work ends
need["Work interval that must not be slept through"] --> a["SetThreadExecutionState"]
need --> b["Power request (PowerSetRequest)"]
a -.-> a1["Convenient, flags only"]
b -.-> b1["With a reason, visible in powercfg"]
a --> off["Always clear it when the work ends"]
b --> off
Figure 8: With either means, “clear it when you finish” is an absolute condition. A power request, which can make the reason visible, is kinder to operations.
If Continuous Operation Is a Requirement, Revisit the Placement and the Operations
Services and windowless apps can also receive the notifications through DEVICE_NOTIFY_CALLBACK with RegisterSuspendResumeNotification.8
If continuous operation is genuinely required, however, reconsider keeping the work resident on a client PC that sleeps at all. Moving the work to the server side or to a machine operated without sleep is the fundamental fix.
6. Investigation — powercfg and the Event Log
For a support ticket, first confirm whether the PC was asleep just before the error. Ask whether the lid was closed and how many minutes the machine was left idle, then use the tool that fits the symptom.
| What to find out | Tool | What to check |
|---|---|---|
| Why it will not sleep | powercfg /requests |
The processes and drivers issuing power requests. Also check for a SetThreadExecutionState that was never cleared |
| Why it wakes on its own | powercfg /lastwake, powercfg /waketimers |
The most recent wake reason, and the timers scheduled to wake the machine |
| Modern Standby quality | powercfg /sleepstudy |
Power consumption and activity per sleep interval9 |
| The timeline of sleep and resume | Kernel-Power in the System event log |
Records of entering sleep and resuming |
Matching the event log against the app’s log lets you confirm objectively whether there was a resume just before the error. Do not stop at suspecting sleep; line up the timestamps and isolate the cause.
flowchart TB
accTitle: Mapping power-trouble symptoms to investigation commands
accDescr: For a will-not-sleep symptom, find who holds a power request with powercfg /requests; for a wakes-on-its-own symptom, find the wake reason with /lastwake and /waketimers; for the timeline, use Kernel-Power in the event log
s1["It will not sleep"] --> c1["powercfg /requests"]
s2["It wakes on its own"] --> c2["powercfg /lastwake and /waketimers"]
s3["Want to check the timeline"] --> c3["Kernel-Power in the event log"]
c1 -.-> note["A sleep suppression that was never cleared shows up too"]
Figure 9: Symptoms map to investigation commands in three families. First confirm “did it sleep just beforehand”, then choose the tool.
7. Summary
Handling sleep is not finished just by receiving the notifications. Allow for preparation not finishing in time and for the resume notification not arriving, and divide the roles as follows.
| Design or investigation target | Points to keep in mind |
|---|---|
| Before sleep | It cannot be refused. Prepare within the roughly 2-second grace period of PBT_APMSUSPEND, but no notification comes in an emergency |
| Resume notifications | Required recovery on PBT_APMRESUMEAUTOMATIC, user-facing work on PBT_APMRESUMESUSPEND. Do not rely on the notifications alone |
| Connections and handles | Center on reconnecting from communication errors, and combine idempotence, exponential backoff, and a keepalive |
| Time | Guard against abnormal elapsed-time differences and rebuild periodic work. Scheduled work does not run while the machine is asleep |
| Sleep suppression | Set it only for the intervals that need it and clear it afterward. Keep the recovery for explicit sleep actions and the like |
| Root-cause investigation | Ask whether the machine slept just beforehand, and match the powercfg and Kernel-Power records against the app’s log |
From the app’s point of view, sleep is an event in which “time jumps without warning, connections to the surroundings are cut, and then everything comes back”. Whether the design treats this as part of everyday operation rather than an abnormal situation is what separates stable business apps from unstable ones in the laptop era.
Related Articles
- Serial Communication App Pitfalls - Through Reconnection and Log Design
- Windows Shutdown as Seen from Your App — Surviving Exit Notifications, Restarts, and Power Loss Correctly
- What Is Windows Efficiency Mode? - The Green Leaf Icon and How to Turn It Off
- Why You Should Prefer Event Waits over Sleep(1) on Windows
- What “Not Responding” Really Is — How Windows Decides an App Has Hung, and How to Design Apps That Don’t
Related Consulting Areas
KomuraSoft LLC handles root-cause investigation of problems such as “communication breaks after resume from sleep” and “the connection to the device drops after the lunch break”, retrofitting reconnect logic and power-event handling onto existing apps, and design reviews of business apps and device-control software built for laptop operation.
- Bug Investigation & Root-Cause Analysis
- Windows Application Development
- Technical Consulting & Design Review
- Contact Us
References
-
Microsoft Learn, PBT_APMSUSPEND event. On this being the event delivered just before the computer enters the suspend state; on the app being expected to complete the work needed to save its data; and on the system allowing about 2 seconds to handle this notification, with an app that keeps processing beyond that being subject to interruption. ↩ ↩2
-
Microsoft Learn, System Power Management Events. On the system broadcasting operating-mode changes such as sleep in advance; on PBT_APMSUSPEND being delivered before idle sleep so the app can prepare by closing files and saving data; on an emergency suspend (critical battery and the like) giving no advance notification; on each app being allowed at most 2 seconds to handle this message and being cut off after the timeout; and on every app being notified on resume. ↩ ↩2 ↩3
-
Microsoft Learn, Prepare software for modern standby. On the Desktop Activity Moderator (DAM) pausing desktop apps at the first stage of the transition into Modern Standby; and on the system then moving in stages into the low-power phase and the resiliency phase, with only permitted components running intermittently. ↩ ↩2 ↩3
-
Microsoft Learn, SetThreadExecutionState function (winbase.h). On ES_SYSTEM_REQUIRED and ES_DISPLAY_REQUIRED suppressing the system’s idle sleep and display power-off; and on declaring continuous suppression with ES_CONTINUOUS and clearing it, once finished, by calling with ES_CONTINUOUS alone. ↩ ↩2
-
Microsoft Learn, PowerSetRequest function (winbase.h). On setting request types such as keeping the system or the display on for a power request object created with PowerCreateRequest; on attaching a diagnostic reason string; and on outstanding power requests being listable with powercfg /requests. ↩ ↩2 ↩3
-
Microsoft Learn, PBT_APMRESUMESUSPEND event. On this being sent after PBT_APMRESUMEAUTOMATIC on a user-initiated resume or when user input is detected afterward; on only PBT_APMRESUMEAUTOMATIC being sent for a resume from an external cause such as a remote wake; and on the app being expected to reopen the files it closed at sleep time and prepare for user input. ↩ ↩2
-
Microsoft Learn, WM_POWERBROADCAST message. On PBT_APMRESUMEAUTOMATIC always being sent on resume, with PBT_APMRESUMESUSPEND sent in addition on a resume from user input; on this message not distinguishing the kind of low-power state; on the details of power-state transitions being recorded in the System event log; and on calling SetThreadExecutionState to prevent the system from entering a low-power state. ↩ ↩2 ↩3
-
Microsoft Learn, RegisterSuspendResumeNotification function (winuser.h). On this being the API that registers to receive suspend and resume notifications, and on specifying DEVICE_NOTIFY_CALLBACK so that, in addition to message delivery to a window handle, a windowless app or service can receive the notifications through a callback. ↩ ↩2
-
Microsoft Learn, Modern standby SleepStudy. On the report generated by powercfg /sleepstudy showing, per Modern Standby interval, power consumption, activity, and the wake reason (power button, user input, wake timer, and so on). ↩
Related Articles
Recent articles sharing the same tags. Deepen your understanding with closely related topics.
DllMain and the Loader Lock — The Real Reason You Are Told to "Do Nothing in DLL Initialization"
Why DllMain must not call LoadLibrary or wait on threads: the loader lock serializes DLL notifications, typical deadlocks, deferred initi...
What "Not Responding" Really Is — How Windows Decides an App Has Hung, and How to Design Apps That Don't
Windows marks a window Not Responding after 5 seconds without message retrieval and shows a ghost window: the check, hang causes, UI-thre...
Decoding Windows Error Codes — The Three-Layer Structure of Win32 Errors, HRESULT, and NTSTATUS
Decompose 0x80004005 before searching. The three layers of Win32 errors, HRESULT, and NTSTATUS, why 0x8007xxxx is a rewrapped Win32 error...
Practical Multithreading Best Practices: C Edition — Writing Safely the Win32 API Way
In C on Win32 the established practice is _beginthreadex, SRW locks and condition variables, Interlocked, and a stop event plus WaitForMu...
Windows App Outsourcing and Custom Software Development: What to Sort Out Before You Ask
Before commissioning Windows app outsourcing or custom software development, here is how to sort out existing software modification, devi...
Related Topics
These topic pages place the article in a broader service and decision context.
Windows Technical Topics
Topic hub for KomuraSoft LLC's Windows development, investigation, and legacy-asset articles.
Bug Investigation & Long-Run Failures
Topic page for intermittent failures, communication diagnosis, long-run crashes, and failure-path test foundations.
Where This Topic Connects
This article connects naturally to the following service pages.
Windows App Development
We support Windows desktop applications that involve resident processing, device integration, operational logging, and maintainable structure.
Bug Investigation & Root Cause Analysis
We investigate difficult production issues such as intermittent failures, long-run crashes, leaks, and communication stoppages.
Frequently Asked Questions
Common questions about the topic of this article.
- Can an app learn in advance that the machine is about to sleep and refuse it?
- On current Windows, an app can receive the notification but cannot refuse. Just before sleep, a WM_POWERBROADCAST message delivers the PBT_APMSUSPEND event, and the app can prepare by closing files and saving state, but the time allowed for processing is about 2 seconds per app; beyond that, the system proceeds without waiting for the app. On an emergency suspend, such as a nearly exhausted battery, no advance notification arrives at all. A design that "must finish before sleep" therefore does not hold; the design has to be one that "can recover on resume no matter when it is cut off". For a stretch of work that really must not be slept through, suppress sleep explicitly with SetThreadExecutionState or a power request (PowerSetRequest).
- How do I detect that the machine has resumed?
- If the app has a window, handle WM_POWERBROADCAST. On resume from suspend, PBT_APMRESUMEAUTOMATIC arrives, and if the resume was caused by a user action (the power button or a key press), PBT_APMRESUMESUSPEND follows. An unattended resume that goes straight back to sleep delivers only PBT_APMRESUMEAUTOMATIC, so the basic split is to put required work such as reconnecting on the PBT_APMRESUMEAUTOMATIC side and user-facing work such as screen updates on the PBT_APMRESUMESUSPEND side. Windowless services and console apps can receive the same notifications through a callback by using RegisterSuspendResumeNotification with DEVICE_NOTIFY_CALLBACK.
- Can I keep the app running during sleep?
- As a rule, no. During sleep, CPU execution itself stops (on a Modern Standby machine, desktop apps are paused by the Desktop Activity Moderator), and the app's code does not run. There are two options. One is to suppress sleep only while the work is in progress. Specifying ES_SYSTEM_REQUIRED with SetThreadExecutionState, or issuing a power request with PowerCreateRequest/PowerSetRequest, suppresses automatic idle sleep for that interval (you can confirm it with powercfg /requests). This still cannot stop an explicit sleep action such as the user closing the lid, so you need to be ready for resume even while suppression is on. The other is to accept sleep and design the app to "catch up after resume". For scheduled work such as a nightly batch, you can also wake the PC with Task Scheduler's "Wake the computer to run this task". Work that truly has to run continuously belongs on a server or a service configured not to sleep.
- Why do TCP connections and serial ports stop working after resume?
- Because network adapters and USB devices also drop into a low-power state during sleep. The TCP connection has already been discarded by the peer or by a NAT or firewall timeout, so send and receive after resume fail (often you do not notice until they fail). A USB-to-serial adapter and similar devices are sometimes treated as a device removal and reinsertion on resume, and the handle that was open becomes invalid. In both cases, the right answer is to assume that "handles and connections do not survive across resume" and implement reconnect logic that rebuilds the connection when a resume notification or a communication error occurs. The established pattern combines a periodic keepalive with retries that use exponential backoff on failure.
- How do I investigate a machine that sleeps on its own or wakes on its own?
- The powercfg command is the first tool. In the "it will not sleep" direction, powercfg /requests lists which processes and drivers have issued power requests that block sleep. In the "it wakes on its own" direction, powercfg /lastwake shows the most recent wake reason, and powercfg /waketimers shows timers currently scheduled to wake the machine. On a Modern Standby machine, powercfg /sleepstudy produces a report of power consumption and activity during sleep. Sleep and resume history is also recorded in the event log (the Kernel-Power source in the System log), so you can confirm on a timeline when the machine slept and when and why it woke.