Aplicaciones que se rompen al reanudar de la suspensión — Eventos de energía y aplicaciones empresariales que sobreviven a la reanudación
· Actualizado el: · Go Komura · Windows, Gestión de energía, Desarrollo en Windows, Aplicaciones empresariales, Control de dispositivos, Investigación de fallos, Win32 API
Historial de revisiones (primera versión, publicada el 22 Aug 2026)
- Primera publicación
Citar este artículo(DOI (archivo registrado): 10.5281/zenodo.22176733)
Los DOI siguientes remiten a versiones ya archivadas y pueden diferir del texto actual. Para citar el texto actual, utilice la URL de esta página.
Go Komura (2026). Aplicaciones que se rompen al reanudar de la suspensión — Eventos de energía y aplicaciones empresariales que sobreviven a la reanudación. KomuraSoft LLC. https://comcomponent.com/es/blog/windows-sleep-resume-power-events/
- DOI (archivo registrado)
- 10.5281/zenodo.22176733
- DOI (última versión registrada)
- 10.5281/zenodo.22176734
Cierra el portátil, lo abre a la mañana siguiente y la aplicación empresarial está llena de errores. Una aplicación de supervisión de equipos pierde datos solo después de la pausa del mediodía. Una herramienta en segundo plano que exporta a Excel se detiene de vez en cuando con un error de conexión. Ante síntomas como estos, lo primero que hay que sospechar es el comportamiento a través de la suspensión.
Algunas aplicaciones empresariales tradicionales se escribieron dando por supuesto que «el PC permanece encendido». Ahora que los portátiles ocupan el centro del trabajo diario, no se puede ignorar un entorno que se suspende en pocos minutos si se deja inactivo. Además, los equipos compatibles con Modern Standby se suspenden por un mecanismo distinto del tradicional.
Este artículo se dirige a desarrolladores que crean aplicaciones empresariales y software de control de equipos en Windows. Organiza, a partir de fuentes primarias, las notificaciones que entrega el sistema operativo, lo que se rompe después de reanudar, cómo diseñar la recuperación y cómo investigar en el terreno, en ese orden.
1. La conclusión primero
El centro del diseño no es «dejarlo todo en orden antes de la suspensión», sino «poder recuperarse después de reanudar, se detenga el equipo cuando se detenga». Hay tres puntos que retener.
- La notificación previa no es una garantía de que podrá terminar. La suspensión no se puede rechazar, y el margen de gracia de
PBT_APMSUSPENDes de unos 2 segundos. En una suspensión de emergencia la notificación no llega. Tampoco bajo Modern Standby puede dar por supuesto que una aplicación de escritorio sigue ejecutándose durante la suspensión.123 - Diseñe dando por supuesto que las conexiones, los handles y la continuidad del tiempo no se conservan a través de la reanudación. Encauce no solo la notificación de reanudación, sino también los errores de comunicación, hacia el mismo procesamiento de reconexión, y revise también las programaciones de temporizadores y las diferencias de tiempo transcurrido.
- La supresión de la suspensión y la preparación para la reanudación son medidas distintas. Use
SetThreadExecutionStateo una solicitud de energía en los intervalos de trabajo que lo necesiten, y retírela siempre después. No puede impedir, sin embargo, una acción de suspensión explícita del usuario, así que no es motivo para omitir la lógica de recuperación.45
También puede empezar por el capítulo que coincida con su objetivo.
| Lo que quiere saber | Capítulo que leer |
|---|---|
| Qué notificaciones llegan antes y después de la suspensión | Capítulo 2: El flujo de los eventos de energía |
| Qué cambia con Modern Standby | Capítulo 3: Comportamiento del sistema y pausa de la aplicación |
| Por qué ocurren errores de conexión y desfase de hora | Capítulo 4: Síntomas clásicos |
| Cómo implementar la reconexión, el tratamiento del tiempo y la supresión de la suspensión | Capítulo 5: Diseño que sobrevive a la reanudación |
| Cómo acotar una consulta de soporte | Capítulo 6: powercfg y el registro de eventos |
2. Qué ocurre alrededor de la suspensión — El flujo de los eventos de energía
El sistema operativo notifica a las aplicaciones los cambios de estado de energía mediante el mensaje WM_POWERBROADCAST.2 Primero, los tres eventos que se usan alrededor de la transición de suspensión. En qué se diferencia la inactividad de bajo consumo de Modern Standby se complementa en el capítulo 3.
| Evento | Significado |
|---|---|
| PBT_APMSUSPEND | A punto de entrar en suspensión (última oportunidad de prepararse) |
| PBT_APMRESUMEAUTOMATIC | Reanudado (llega siempre al reanudar) |
| PBT_APMRESUMESUSPEND | Reanudación causada por una acción del usuario (este es condicional) |
sequenceDiagram
accTitle: Flujo de notificaciones de suspensión y reanudación
accDescr: PBT_APMSUSPEND llega justo antes de la suspensión con unos 2 segundos de margen; al reanudar, PBT_APMRESUMEAUTOMATIC llega siempre, y PBT_APMRESUMESUSPEND solo sigue en una reanudación iniciada por el usuario
participant OS as OS
participant A as Aplicación
OS->>A: PBT_APMSUSPEND (unos 2 segundos de margen)
A->>A: Guardar el estado y cerrar las conexiones
Note over OS: Suspensión (el código no se ejecuta)
OS->>A: PBT_APMRESUMEAUTOMATIC (llega al reanudar)
A->>A: Reconectar y reconstruir el estado
OS->>A: PBT_APMRESUMESUSPEND (solo reanudación iniciada por el usuario)
A->>A: Actualizaciones de pantalla y otro trabajo orientado al usuario
Figura 1: Las notificaciones se reducen a «una palabra justo antes, y una o dos después de reanudar». El procesamiento del lado de la reanudación es el que impulsa la recuperación.
La notificación previa a la suspensión es la oportunidad de «prepararse si da tiempo»
PBT_APMSUSPEND es la notificación que se entrega justo antes de entrar en suspensión. Permite cerrar archivos y guardar el estado, pero tiene las dos restricciones siguientes.
| Restricción | Efecto en el diseño |
|---|---|
| El margen de gracia es de unos 2 segundos por aplicación | Más allá de ese tiempo, el sistema continúa sin esperar a la aplicación1 |
| Una suspensión de emergencia no da notificación previa | Cuando el nivel de batería es crítico, por ejemplo, el equipo se detiene sin ninguna preparación2 |
Por tanto, un diseño que «siempre termina de guardar después de recibir esta notificación» no se sostiene. Use la notificación previa para preparar lo que aún dé tiempo, y ponga el fondo de la recuperación del lado de la reanudación.
flowchart TB
accTitle: Diferencia entre suspensión ordinaria y suspensión de emergencia
accDescr: La suspensión ordinaria entrega PBT_APMSUSPEND justo antes con unos 2 segundos para prepararse, pero una suspensión de emergencia causada por una batería crítica o similar se detiene sin notificación previa, de modo que un diseño que depende de la notificación previa no se sostiene
n2["Suspensión ordinaria"] --> pre["PBT_APMSUSPEND (unos 2 segundos de margen)"]
pre --> s1["Prepararse y luego detenerse"]
e2["Suspensión de emergencia (batería casi agotada)"] --> s2["Detenerse sin notificación previa"]
s2 -.-> l2["Un diseño que da por sentado que llegará la notificación no se sostiene"]
Figura 2: Una suspensión de emergencia llega sin aviso. La preparación es, pues, «una ganancia si llega a tiempo», y el fondo va del lado de la reanudación.
Las notificaciones de reanudación separan la recuperación mecánica y el trabajo orientado al usuario
Al reanudar desde la suspensión, llega primero PBT_APMRESUMEAUTOMATIC. Si el equipo se reanudó por el botón de encendido o una pulsación de tecla, o si se detectó la presencia del usuario después de reanudar, sigue PBT_APMRESUMESUSPEND.67
En cambio, en una reanudación desatendida como un despertar remoto por la red o una reanudación para mantenimiento, solo llega PBT_APMRESUMEAUTOMATIC. Ponga la recuperación necesaria, como reconstruir las conexiones, en la primera, y las acciones orientadas al usuario, como las actualizaciones de pantalla o una petición de volver a iniciar sesión, en la segunda.6
flowchart TB
accTitle: Reparto del trabajo en las dos etapas de reanudación
accDescr: Ponga la recuperación mecánica, como reconectar, en PBT_APMRESUMEAUTOMATIC, que llega al reanudar; ponga el trabajo orientado al usuario, como las actualizaciones de pantalla o una petición de volver a iniciar sesión, en PBT_APMRESUMESUSPEND, que solo llega en una reanudación iniciada por el usuario
ra["PBT_APMRESUMEAUTOMATIC (al reanudar)"] --> m["Recuperación mecánica"]
rs["PBT_APMRESUMESUSPEND (reanudación iniciada por el usuario)"] --> u["Trabajo orientado al usuario"]
m -.-> m1["Reconectar y reabrir handles"]
u -.-> u1["Actualizaciones de pantalla y petición de volver a iniciar sesión"]
Figura 3: La segunda no llega en una reanudación desatendida, así que si pone la recuperación necesaria en la segunda la perderá.
Las aplicaciones sin ventana también pueden recibir las notificaciones
Los servicios sin ventana y las aplicaciones de consola pueden usar RegisterSuspendResumeNotification con DEVICE_NOTIFY_CALLBACK y recibir las mismas notificaciones mediante una devolución de llamada.8
Además, WM_POWERBROADCAST no puede indicar si el estado de bajo consumo era suspensión o hibernación.7 La aplicación debe diseñar su recuperación en torno al evento común «se detuvo y volvió».
3. Modern Standby — El significado de «suspensión» ha cambiado
Que el sistema funcione y que la aplicación pueda funcionar son cosas distintas
La suspensión S3 tradicional es un modelo que detiene el sistema entero. Modern Standby, en cambio, es un modelo cercano al del teléfono en el que el sistema sigue funcionando de forma intermitente después de apagar la pantalla.
Eso no significa, sin embargo, que las aplicaciones de escritorio ordinarias sigan ejecutándose. En la primera etapa de la entrada en suspensión, las pausa el Desktop Activity Moderator (DAM).3
| Modo | Comportamiento del sistema | Supuesto para las aplicaciones de escritorio |
|---|---|---|
| Suspensión S3 tradicional | El sistema entero se detiene | El código no se ejecuta durante la suspensión |
| Modern Standby | Funciona de forma intermitente para mantener la red, recibir notificaciones, etc. | Las pausa el DAM; el código ordinario no se ejecuta |
Los componentes que se benefician de la actividad intermitente son los construidos para este mecanismo. Para el diseño de una aplicación empresarial, la conclusión es la misma en ambos casos: «el código propio no se ejecuta durante la suspensión».3
flowchart TB
accTitle: Diferencia entre la suspensión tradicional y Modern Standby
accDescr: La suspensión S3 tradicional detiene el sistema entero, mientras que bajo Modern Standby el sistema sigue funcionando de forma intermitente después de apagar la pantalla. Las aplicaciones de escritorio, sin embargo, las pausa el DAM, así que el código de la aplicación no se ejecuta en ninguno de los dos casos
s3["Suspensión S3 tradicional: el sistema entero se detiene"] --> conc["El código de la aplicación no se ejecuta"]
ms["Modern Standby: el sistema funciona de forma intermitente"] --> dam["Las aplicaciones de escritorio las pausa el DAM"]
dam --> conc
Figura 4: El modelo ha cambiado, pero para una aplicación de escritorio la conclusión es la misma: «no puede ejecutarse durante la suspensión».
No haga de la notificación de reanudación la única condición de la recuperación
La entrada y la salida de la inactividad de bajo consumo de Modern Standby no coinciden siempre con la transición de suspensión tradicional. Una conexión puede estar ya rota sin que haya llegado ninguna notificación. Trate la notificación de reanudación como una ayuda que acelera la recuperación, y ponga en el centro un camino que reconecte al detectar un error de comunicación. La estructura concreta se explica en el capítulo 5.
Además, como la transición al estado de bajo consumo es gradual, el momento de las desconexiones y las detenciones no es tan nítido como bajo S3. A los usuarios también les cuesta distinguir «la pantalla acaba de apagarse» de «se ha suspendido», así que cuando reciba un informe de síntoma, confirme si se cerró la tapa y cuántos minutos se dejó el equipo inactivo.
4. Qué se rompe — Síntomas clásicos
Los errores después de reanudar se organizan en conexiones, handles de dispositivos y continuidad del tiempo. En recursos compartidos, compruebe también cuánto tardan la reautenticación y el restablecimiento de la red.
Una conexión TCP no se entera de la desconexión hasta enviar o recibir
Durante la suspensión, el interlocutor, los equipos NAT y los firewalls tratan su silencio como un tiempo de espera y descartan la conexión. El socket de este lado, sin embargo, no lo sabe, así que falla solo cuando envía o recibe después de reanudar.
A veces una recepción pendiente no produce nunca un error. Por eso hace falta un keepalive que compruebe si la conexión está viva. Las conexiones de base de datos y los WebSocket siguen el mismo patrón.
Los puertos serie y los dispositivos USB necesitan que se reabran sus handles
Un dispositivo USB puede, al reanudar, parecer que se desenchufó y se volvió a enchufar, y el handle que estaba abierto empieza a devolver errores. Es el patrón típico de una aplicación de control de equipos que «solo tiene un error de comunicación después de la pausa del mediodía».
En lugar de dar por supuesto que el handle sigue siendo usable, estructure la aplicación para que pueda reabrir el dispositivo. El diseño de la reconexión también se trata en el artículo de comunicación serie.
Revisar por separado el trabajo periódico, el tiempo transcurrido y el trabajo programado
Los problemas relacionados con el tiempo se dividen en los tres tipos siguientes.
| Trabajo | Qué ocurre a través de la suspensión | Contramedida |
|---|---|---|
| Trabajo periódico como «consultar cada 10 segundos» | Se detiene durante la suspensión. Cómo se dispara después de reanudar depende de la API y del entorno de ejecución | Reconstruir la programación al reanudar |
| Cálculos que usan la diferencia respecto a la marca de tiempo anterior | La diferencia se convierte de pronto en «el equivalente de 8 horas», y los promedios o los juicios de tiempo de espera se rompen | Protegerse de diferencias anormalmente grandes |
| Trabajo programado como «ejecutar todas las noches a las 2» | No se ejecuta si el PC está suspendido a esa hora | Usar si hace falta la función de reactivación del Programador de tareas |
El trabajo periódico, en particular, puede dispararse una vez justo después de reanudar por el tick vencido, o no ocurrir nada hasta el periodo siguiente. No deje el tratamiento de las ejecuciones perdidas al comportamiento implícito del temporizador.
flowchart TB
accTitle: Tres formas en las que se rompe la continuidad del tiempo
accDescr: El trabajo periódico se detiene durante la suspensión y el disparo posterior a la reanudación difiere según la API, así que reconstruya la programación al reanudar; la diferencia respecto a la marca de tiempo anterior se vuelve enorme después de reanudar, así que protéjala; el trabajo programado no se ejecuta si el equipo está suspendido, así que considere la reactivación desde la suspensión del Programador de tareas
t1["Trabajo periódico: se detiene durante la suspensión"] -.-> g1["Reconstruir la programación al reanudar"]
t2["Diferencia de tiempo transcurrido: explota"] -.-> g2["Protegerse de diferencias anómalas"]
t3["Trabajo programado: suspendido, nunca se ejecutó"] -.-> g3["Despertar el equipo con un ajuste de reactivación"]
Figura 5: Escriba el tratamiento de temporizadores y reloj dando por supuesto que «el tiempo salta». Cada una de las tres formas tiene su propio tipo de contramedida.
flowchart TB
accTitle: Tres cosas que se rompen a través de la suspensión
accDescr: A través de la suspensión, una conexión TCP la descarta un tiempo de espera del interlocutor, el handle de un dispositivo USB queda invalidado como si se hubiera reconectado, y el trabajo basado en tiempo transcurrido observa un salto de tiempo enorme. Recupere cada uno con reconexión, reapertura y protección de diferencia
sleep["Intervalo de suspensión"] --> tcp["Conexión TCP: descartada por el interlocutor"]
sleep --> usb["Dispositivo USB: handle invalidado"]
sleep --> time["Tiempo transcurrido: un salto enorme"]
tcp -.-> r1["Detectar el error y reconectar"]
usb -.-> r2["Reabrir el dispositivo"]
time -.-> r3["Protegerse de diferencias anómalas"]
Figura 6: Lo que se rompe cae en tres familias, «conexiones», «handles» y «continuidad del tiempo», y cada una tiene un tipo de recuperación asentado.
Las unidades de red y las VPN tienen un periodo de espera justo después de reanudar
Las unidades de red y las VPN a veces necesitan reautenticación y restablecimiento después de reanudar. Por eso hay una ventana de unos segundos a unas decenas de segundos justo después de reanudar en la que el acceso falla.
En lugar de reintentarlo todo de golpe en el momento en que el equipo reanuda, diseñe la aplicación para esperar un poco y reintentar por etapas.
5. Cómo construir aplicaciones que sobrevivan a la reanudación
El principio es estructurar la aplicación para que pueda recuperarse en cualquier momento, aunque las conexiones y los handles no sobrevivan a través de la suspensión. Diseñe por separado la reconexión, el tratamiento del tiempo y la supresión de la suspensión para los intervalos que la necesiten.
Hacer converger la notificación de reanudación y los errores de comunicación en el mismo procesamiento de reconexión
Cuando el WM_POWERBROADCAST de la ventana de nivel superior reciba PBT_APMRESUMEAUTOMATIC, descarte las conexiones que conserva y reconstruya. Sin embargo, no se fíe solo de la notificación de reanudación. Las notificaciones se pueden perder, y puede haber comunicación antes de que llegue la notificación.
Proporcione siempre un camino que «reconecte cuando se detecte un error de comunicación», y trate la notificación de reanudación como un disparador que inicia ese trabajo antes. El siguiente ejemplo en C# es la parte que solicita una reconexión desde la notificación de reanudación. El lado del error de comunicación converge en el mismo procesamiento de reconexión.
// C#: hacer converger la notificación de reanudación y los errores de comunicación en el mismo procesamiento de reconexión
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(); // solicitud de reconexión idempotente
}
base.WndProc(ref m);
}
La reconexión combina «idempotencia, retroceso y keepalive»
El procesamiento de reconexión necesita juntos los tres elementos siguientes.
| Elemento | Función |
|---|---|
| Reconexión idempotente | Recuperarse con seguridad, se solicite las veces que se solicite |
| Reintentos con retroceso exponencial | Alargar el intervalo hasta el siguiente intento después de un fallo |
| Keepalive en régimen establecido | Confirmar que la conexión está viva y detectar una desconexión pronto |
Este conjunto de tres elementos ayuda no solo a la reanudación desde la suspensión, sino tal cual a caídas breves de red y a reinicios de dispositivos.
flowchart TB
accTitle: Diseño de reconexión que sobrevive a la reanudación
accDescr: La notificación de reanudación, un error de comunicación y un fallo de keepalive convergen todos en el mismo procesamiento de reconexión idempotente, que reintenta con retroceso exponencial ante un fallo
e1["Notificación de reanudación (PBT_APMRESUMEAUTOMATIC)"] --> r["Procesamiento de reconexión idempotente"]
e2["Error de comunicación detectado"] --> r
e3["Fallo de keepalive"] --> r
r --> ok{"¿Ha funcionado?"}
ok -->|"Sí"| run["Vuelta al funcionamiento normal"]
ok -->|"No"| back["Reintentar tras retroceso exponencial"]
back --> r
Figura 7: Concentre la reconexión en un solo camino idempotente, y entre por la misma vía desde la notificación de reanudación, la detección de error o el keepalive.
No mezcle en los cálculos un intervalo en el que el tiempo saltó
En el trabajo que usa «el tiempo transcurrido desde la última vez», añada una protección que invalide el intervalo cuando detecte una diferencia anormalmente grande. El punto es no plegarla en un promedio y no tratarla como un tiempo de espera ordinario.
Al medir el tiempo a través de la reanudación, distinga el reloj que sigue avanzando durante la suspensión (hora civil) del tiempo realmente dedicado al trabajo. La reconstrucción de la programación del trabajo periódico y el tratamiento del trabajo programado que no se ejecutó también deben revisarse con las categorías del capítulo 4.
Suprima la suspensión de forma explícita para el trabajo que no debe interrumpirse
Mientras está en curso un trabajo que no debe suspenderse, como una migración de datos o una comunicación continua con un dispositivo, use SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED). Si también quiere mantener la pantalla encendida, añada ES_DISPLAY_REQUIRED.74
El otro medio es una solicitud de energía a través de PowerCreateRequest y PowerSetRequest. Como puede adjuntar una cadena de motivo, powercfg /requests muestra «quién está bloqueando la suspensión, y por qué». Este es más amable en que el personal de operaciones puede leer el motivo.5
| Medio | Unidad de gestión y precauciones |
|---|---|
SetThreadExecutionState |
Por hilo. Retírela desde el mismo hilo que la estableció |
Solicitud de energía (PowerCreateRequest + PowerSetRequest) |
Se gestiona con un handle. Use esta para trabajo que cambia de hilo, como async/await |
Sin embargo, establecer la supresión no impide todo tipo de interrupción. Compruebe las restricciones siguientes por separado de la lógica de recuperación.
| Restricción | Respuesta necesaria |
|---|---|
| Lo que se suprime es la suspensión automática por inactividad | Conserve la lógica de reconexión para acciones explícitas como cerrar la tapa o elegir Suspender en el menú Inicio |
| En un equipo Modern Standby con batería, las solicitudes de energía también se cortan un tiempo después del tiempo de espera de suspensión | Garantice el trabajo ininterrumpible con alimentación de CA o del lado de operaciones5 |
| Un olvido de retirada hace que el PC no pueda suspenderse | Retírela siempre cuando el trabajo termine |
flowchart TB
accTitle: Dos medios de suprimir la suspensión
accDescr: Tanto si usa el práctico SetThreadExecutionState como la API de solicitud de energía que puede adjuntar una cadena de motivo y es visible para un administrador a través de powercfg, retírela siempre cuando el trabajo termine
need["Intervalo de trabajo que no debe suspenderse"] --> a["SetThreadExecutionState"]
need --> b["Solicitud de energía (PowerSetRequest)"]
a -.-> a1["Práctico, solo marcas"]
b -.-> b1["Con motivo, visible en powercfg"]
a --> off["Retirar siempre al terminar el trabajo"]
b --> off
Figura 8: Con cualquiera de los dos medios, «retirarla cuando termine» es una condición absoluta. Una solicitud de energía, que puede hacer visible el motivo, es más amable para las operaciones.
Si el funcionamiento continuo es un requisito, revise la ubicación y las operaciones
Los servicios y las aplicaciones sin ventana también pueden recibir las notificaciones a través de DEVICE_NOTIFY_CALLBACK con RegisterSuspendResumeNotification.8
Si el funcionamiento continuo es realmente necesario, sin embargo, reconsidere mantener el trabajo residente en un PC cliente que se suspende. Mover el trabajo al lado del servidor o a un equipo operado sin suspensión es la corrección de raíz.
6. Investigación — powercfg y el registro de eventos
En una consulta de soporte, confirme primero si el PC estaba suspendido justo antes del error. Pregunte si se cerró la tapa y cuántos minutos se dejó el equipo inactivo, y luego use la herramienta que encaje con el síntoma.
| Lo que quiere averiguar | Herramienta | Qué comprobar |
|---|---|---|
| Por qué no se suspende | powercfg /requests |
Los procesos y controladores que emiten solicitudes de energía. Compruebe también un SetThreadExecutionState que nunca se retiró |
| Por qué se despierta solo | powercfg /lastwake, powercfg /waketimers |
El motivo de reactivación más reciente y los temporizadores reservados para despertar el equipo |
| Calidad de Modern Standby | powercfg /sleepstudy |
Consumo y actividad por intervalo de suspensión9 |
| La línea de tiempo de suspensión y reanudación | Kernel-Power en el registro de eventos Sistema |
Registros de la entrada en suspensión y de la reanudación |
Al cruzar el registro de eventos con el registro de la aplicación, puede confirmar de forma objetiva si hubo una reanudación justo antes del error. No se quede en sospechar de la suspensión; alinee las marcas de tiempo y aísle la causa.
flowchart TB
accTitle: Correspondencia entre síntomas de energía y comandos de investigación
accDescr: Para un síntoma no-se-suspende, encuentre quién retiene una solicitud de energía con powercfg /requests; para un síntoma se-despierta-solo, encuentre el motivo de reactivación con /lastwake y /waketimers; para la línea de tiempo, use Kernel-Power en el registro de eventos
s1["No se suspende"] --> c1["powercfg /requests"]
s2["Se despierta solo"] --> c2["powercfg /lastwake y /waketimers"]
s3["Querer comprobar la línea de tiempo"] --> c3["Kernel-Power en el registro de eventos"]
c1 -.-> note["Una supresión de suspensión nunca retirada también aparece"]
Figura 9: Los síntomas se corresponden con los comandos de investigación en tres familias. Confirme primero «si se suspendió justo antes» y luego elija la herramienta.
7. Resumen
El tratamiento de la suspensión no termina solo con recibir las notificaciones. Cuente con que la preparación no llegue a tiempo y con que la notificación de reanudación no llegue, y reparta los papeles como sigue.
| Objetivo de diseño o investigación | Puntos que retener |
|---|---|
| Antes de la suspensión | No se puede rechazar. Prepárese en el margen de unos 2 segundos de PBT_APMSUSPEND, pero en una emergencia no llega notificación |
| Notificaciones de reanudación | Recuperación necesaria en PBT_APMRESUMEAUTOMATIC, trabajo orientado al usuario en PBT_APMRESUMESUSPEND. No se fíe solo de las notificaciones |
| Conexiones y handles | Centre en reconectar desde errores de comunicación, y combine idempotencia, retroceso exponencial y keepalive |
| Tiempo | Protéjase de diferencias anómalas de tiempo transcurrido y reconstruya el trabajo periódico. El trabajo programado no se ejecuta mientras el equipo está suspendido |
| Supresión de la suspensión | Establézcala solo en los intervalos que la necesiten y retírela después. Conserve la recuperación para acciones de suspensión explícitas y similares |
| Investigación de causa | Pregunte si el equipo se suspendió justo antes, y cruce los registros de powercfg y Kernel-Power con el registro de la aplicación |
Desde el punto de vista de la aplicación, la suspensión es un evento en el que «el tiempo salta sin aviso, se cortan las conexiones con el entorno y luego todo vuelve». Que el diseño trate esto como parte de lo cotidiano y no como una situación anómala es lo que separa las aplicaciones empresariales estables de las inestables en la era del portátil.
Artículos relacionados
- Puntos débiles de las aplicaciones de comunicación serie - hasta el diseño de la reconexión y los registros
- El apagado de Windows visto desde la aplicación ── cómo sobrevivir correctamente a la notificación de cierre, el reinicio y el corte de energía
- Qué es el modo de eficiencia de Windows — el icono de hoja verde y cómo desactivarlo
- Por qué priorizar la espera por eventos sobre Sleep(1) en Windows
- Qué es realmente «No responde» — Cómo decide Windows que una aplicación se ha colgado, y cómo diseñar aplicaciones que no lo hagan
Áreas de consultoría relacionadas
En KomuraSoft LLC nos encargamos de investigaciones de causa de problemas como «la comunicación se rompe después de reanudar de la suspensión» y «la conexión con el equipo se corta después de la pausa del mediodía», de añadir a posteriori lógica de reconexión y tratamiento de eventos de energía a aplicaciones existentes, y de revisiones de diseño de aplicaciones empresariales y software de control de equipos construidos para el funcionamiento en portátil.
- Investigación de fallos y análisis de causas
- Desarrollo de aplicaciones Windows
- Consultoría técnica y revisión de diseño
- Contacto
Referencias
-
Microsoft Learn, PBT_APMSUSPEND event. Sobre que este es el evento que se entrega justo antes de que el equipo entre en el estado de suspensión; sobre que se espera que la aplicación complete el trabajo necesario para guardar sus datos; y sobre que el sistema concede unos 2 segundos para tratar esta notificación, y una aplicación que sigue procesando más allá puede interrumpirse. ↩ ↩2
-
Microsoft Learn, System Power Management Events. Sobre que el sistema difunde de antemano los cambios de modo de funcionamiento como la suspensión; sobre que PBT_APMSUSPEND se entrega antes de la suspensión por inactividad para que la aplicación pueda prepararse cerrando archivos y guardando datos; sobre que una suspensión de emergencia (batería crítica y similares) no da notificación previa; sobre que cada aplicación dispone de como máximo 2 segundos para tratar este mensaje y se corta tras el tiempo de espera; y sobre que se notifica a todas las aplicaciones al reanudar. ↩ ↩2 ↩3
-
Microsoft Learn, Prepare software for modern standby. Sobre que el Desktop Activity Moderator (DAM) pausa las aplicaciones de escritorio en la primera etapa de la transición a Modern Standby; y sobre que el sistema pasa después por etapas a la fase de bajo consumo y a la fase de resiliencia, y solo los componentes permitidos funcionan de forma intermitente. ↩ ↩2 ↩3
-
Microsoft Learn, SetThreadExecutionState function (winbase.h). Sobre que ES_SYSTEM_REQUIRED y ES_DISPLAY_REQUIRED suprimen la suspensión por inactividad del sistema y el apagado de la pantalla; y sobre declarar una supresión continua con ES_CONTINUOUS y retirarla, una vez terminado, llamando solo con ES_CONTINUOUS. ↩ ↩2
-
Microsoft Learn, PowerSetRequest function (winbase.h). Sobre establecer tipos de solicitud como mantener el sistema o la pantalla encendidos en un objeto de solicitud de energía creado con PowerCreateRequest; sobre adjuntar una cadena de motivo de diagnóstico; y sobre que las solicitudes de energía pendientes se pueden enumerar con powercfg /requests. ↩ ↩2 ↩3
-
Microsoft Learn, PBT_APMRESUMESUSPEND event. Sobre que se envía después de PBT_APMRESUMEAUTOMATIC en una reanudación iniciada por el usuario o cuando se detecta entrada del usuario a continuación; sobre que solo se envía PBT_APMRESUMEAUTOMATIC en una reanudación por una causa externa como un despertar remoto; y sobre que se espera que la aplicación reabra los archivos que cerró al suspenderse y se prepare para la entrada del usuario. ↩ ↩2
-
Microsoft Learn, WM_POWERBROADCAST message. Sobre que PBT_APMRESUMEAUTOMATIC se envía siempre al reanudar, y PBT_APMRESUMESUSPEND se envía además en una reanudación desde entrada del usuario; sobre que este mensaje no distingue el tipo de estado de bajo consumo; sobre que los detalles de las transiciones de estado de energía se registran en el registro de eventos Sistema; y sobre llamar a SetThreadExecutionState para impedir que el sistema entre en un estado de bajo consumo. ↩ ↩2 ↩3
-
Microsoft Learn, RegisterSuspendResumeNotification function (winuser.h). Sobre que esta es la API que se registra para recibir notificaciones de suspensión y reanudación, y sobre indicar DEVICE_NOTIFY_CALLBACK para que, además de la entrega de mensajes a un handle de ventana, una aplicación o un servicio sin ventana pueda recibir las notificaciones mediante una devolución de llamada. ↩ ↩2
-
Microsoft Learn, Modern standby SleepStudy. Sobre que el informe generado por powercfg /sleepstudy muestra, por intervalo de Modern Standby, el consumo, la actividad y el motivo de reactivación (botón de encendido, entrada del usuario, temporizador de reactivación, etc.). ↩
Artículos relacionados
Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.
DllMain y el bloqueo del cargador — La razón real de que le digan «no haga nada en la inicialización de la DLL»
Por qué no debe llamar a LoadLibrary ni sincronizar con otros hilos desde DllMain. A partir de fuentes primarias, este artículo explica e...
Qué es realmente «No responde» — Cómo decide Windows que una aplicación se ha colgado, y cómo diseñar aplicaciones que no lo hagan
«No responde» de Windows es un mecanismo en el que el sistema operativo juzga que una ventana no ha recuperado un mensaje durante 5 segun...
Cómo interpretar los códigos de error de Windows — la estructura de tres capas de Win32, HRESULT y NTSTATUS
Si aparece 0x80004005, descompóngalo antes de buscar. La estructura de tres capas de Win32, HRESULT y NTSTATUS, el patrón 0x8007xxxx y có...
Buenas prácticas de multithreading en la práctica: edición C — escribir con seguridad al estilo de la API Win32
En C con Win32 la práctica establecida es _beginthreadex, bloqueos SRW y variables de condición, Interlocked, y un evento de detención má...
Qué queda después de que muere el padre — mantener los procesos hijos en un Job Object
Por qué los ayudantes del SDK sobreviven a una IU terminada y retienen la cámara o el puerto COM. Cómo diseñar la vida de los procesos hi...
Temas relacionados
Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.
Temas técnicos de Windows
Portal sobre desarrollo de Windows, investigación de fallos y aprovechamiento de activos existentes.
Investigación de fallos y problemas prolongados
Fallos intermitentes, diagnóstico de comunicaciones, bloqueos prolongados y pruebas de rutas de error.
Servicios relacionados con este tema
El artículo está directamente relacionado con los siguientes servicios.
Desarrollo de aplicaciones para Windows
Aplicaciones empresariales, integración de dispositivos y herramientas de comunicación, de los requisitos al desarrollo.
Preguntas frecuentes
Preguntas habituales en las consultas sobre el tema del artículo.
- ¿Puede una aplicación enterarse de antemano de que el equipo va a suspenderse y rechazarlo?
- En el Windows actual, una aplicación puede recibir la notificación, pero no puede rechazarla. Justo antes de la suspensión, un mensaje WM_POWERBROADCAST entrega el evento PBT_APMSUSPEND; la aplicación puede prepararse cerrando archivos y guardando el estado, pero el tiempo permitido para el procesamiento es de unos 2 segundos por aplicación. Si lo supera, el sistema continúa sin esperar. En una suspensión de emergencia, como una batería casi agotada, no llega ninguna notificación previa. Por tanto, un diseño que «debe terminar antes de la suspensión» no se sostiene; el diseño tiene que poder recuperarse al reanudar, ocurra el corte cuando ocurra. Para un tramo de trabajo por el que de verdad no quiere que se suspenda, suprima la suspensión de forma explícita con SetThreadExecutionState o una solicitud de energía (PowerSetRequest).
- ¿Cómo detecto que el equipo se ha reanudado?
- Si la aplicación tiene una ventana, maneje WM_POWERBROADCAST. Al reanudar desde la suspensión llega PBT_APMRESUMEAUTOMATIC y, si la reanudación la causó una acción del usuario (el botón de encendido o una pulsación de tecla), a continuación llega PBT_APMRESUMESUSPEND. Una reanudación desatendida que vuelve a suspenderse de inmediato entrega solo PBT_APMRESUMEAUTOMATIC, así que la división básica es poner el trabajo necesario, como reconectar, del lado de PBT_APMRESUMEAUTOMATIC, y el trabajo orientado al usuario, como las actualizaciones de pantalla, del lado de PBT_APMRESUMESUSPEND. Los servicios sin ventana y las aplicaciones de consola pueden recibir las mismas notificaciones mediante una devolución de llamada usando RegisterSuspendResumeNotification con DEVICE_NOTIFY_CALLBACK.
- ¿Puedo mantener la aplicación en ejecución durante la suspensión?
- Por regla general, no. Durante la suspensión se detiene la propia ejecución de la CPU (en un equipo con Modern Standby, las aplicaciones de escritorio las pausa el Desktop Activity Moderator), y el código de la aplicación no se ejecuta. Hay dos opciones. Una es suprimir la suspensión solo mientras el trabajo está en curso. Indicar ES_SYSTEM_REQUIRED con SetThreadExecutionState, o emitir una solicitud de energía con PowerCreateRequest/PowerSetRequest, suprime la suspensión automática por inactividad durante ese intervalo (puede comprobarlo con powercfg /requests). Eso no puede detener una acción de suspensión explícita, como que el usuario cierre la tapa, así que sigue haciendo falta estar preparado para la reanudación incluso mientras la supresión está activa. La otra es aceptar la suspensión y diseñar la aplicación para «ponerse al día después de reanudar». Para trabajo programado, como un lote nocturno, también puede despertar el PC con «Reactivar el equipo para ejecutar esta tarea» del Programador de tareas. El trabajo que de verdad necesita ejecutarse de forma continua pertenece a un servidor o a un servicio configurado para no suspenderse.
- ¿Por qué las conexiones TCP y los puertos serie dejan de funcionar después de reanudar?
- Porque los adaptadores de red y los dispositivos USB también entran en un estado de bajo consumo durante la suspensión. La conexión TCP ya la ha descartado el interlocutor o un tiempo de espera de NAT o de un firewall, así que el envío y la recepción después de reanudar fallan (a menudo no se entera hasta que fallan). Los adaptadores USB-serie y similares a veces se tratan como una extracción y reinserción del dispositivo al reanudar, y el handle que estaba abierto deja de ser válido. En ambos casos, el supuesto correcto es que «los handles y las conexiones no sobreviven a través de la reanudación», y la respuesta correcta es implementar una lógica de reconexión que reconstruya la conexión ante una notificación de reanudación o un error de comunicación. El patrón establecido combina un keepalive periódico con reintentos que usan retroceso exponencial ante un fallo.
- ¿Cómo investigo un equipo que se suspende solo o se despierta solo?
- El comando powercfg es la primera herramienta. En la dirección «no se suspende», powercfg /requests enumera qué procesos y controladores han emitido una solicitud de energía que está bloqueando la suspensión. En la dirección «se despierta solo», powercfg /lastwake muestra el motivo de reactivación más reciente y powercfg /waketimers muestra los temporizadores que están reservados en ese momento para despertar el equipo. En un equipo con Modern Standby, powercfg /sleepstudy produce un informe de consumo y actividad durante la suspensión. El historial de suspensión y reanudación también se registra en el registro de eventos (el origen Kernel-Power del registro Sistema), de modo que puede comprobar en una línea de tiempo cuándo se suspendió el equipo, y cuándo y por qué se despertó.
Perfil del autor
Página de presentación del autor del artículo.
Go Komura
Representante de KomuraSoft LLC
Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.