1. 首页 > 服务器系统 > Windows

Windows系统进入了休眠或睡眠状态怎么办?如何解决?一文详解

Windows 11 休眠问题深度解析与解决方案

问题背景

在开发需要长时间持续运行的应用程序时(如工业控制软件、PLC 通信程序、数据采集系统等),经常会遇到以下问题:

  • 程序运行一段时间后自动停止响应
  • 设备通信连接突然断开
  • 远程连接无法访问
  • 定时任务没有执行

根本原因:Windows 系统进入了休眠或睡眠状态,导致程序暂停或终止运行。

Windows 电源管理机制详解

Windows 提供了多种省电模式,每种模式对程序运行的影响各不相同:

1. 睡眠模式(Sleep / S3)

传统睡眠状态(S3)

工作原理

  • CPU 进入低功耗状态
  • 内存(RAM)保持供电,数据保留
  • 硬盘、网络等外设断电
  • 显示器关闭

对程序的影响

  • 用户程序暂停执行
  • 网络连接断开
  • USB 设备可能断电
  • 唤醒后可以恢复

适用场景

  • 短时间离开(几分钟到几小时)
  • 需要快速恢复工作

现代待机(Modern Standby / S0)

工作原理

  • CPU 保持极低功耗运行
  • 内存持续供电
  • 保持网络连接(Connected Standby)
  • 特定应用可以后台运行

对程序的影响

  • 特定程序可以继续运行
  • 网络保持连接
  • 推送通知正常工作
  • 非白名单程序仍会暂停

适用场景

  • 笔记本合盖
  • 类似手机的"息屏"状态

2. 休眠模式(Hibernate / S4)

工作原理

  • 将内存数据完整写入硬盘(hiberfil.sys)
  • CPU、内存、所有外设完全断电
  • 相当于"关机 + 保存状态"

对程序的影响

  • 所有程序完全停止
  • 网络连接断开
  • 所有硬件停止工作
  • 唤醒后恢复到之前状态

适用场景

  • 长时间不使用(数小时到数天)
  • 笔记本电量耗尽时自动进入

3. 混合睡眠(Hybrid Sleep)

工作原理

  • 结合睡眠和休眠的特点
  • 内存保持供电的同时,也将数据写入硬盘
  • 正常情况下像睡眠一样快速唤醒
  • 意外断电时可以从硬盘恢复

对程序的影响

  • 类似传统睡眠(S3)
  • 台式机默认开启

4. 快速启动(Fast Startup)

工作原理

  • 关机时保存系统内核状态到硬盘
  • 下次开机时快速加载
  • 用户会话不保存

对程序的影响

  • 程序完全关闭
  • 不影响正常运行

如何查看系统支持的休眠模式

方法一:使用 PowerShell 命令(推荐)

打开 PowerShell命令提示符,输入:

powercfg /a

输出示例解读:

示例 1:笔记本(支持现代待机)

方法一:使用 PowerShell 命令(推荐)

此系统上有以下睡眠状态:
    待机 (S0 低电量待机) 连接的网络
    休眠
    快速启动
此系统上没有以下睡眠状态:
    待机 (S1)
        系统固件不支持此待机状态。
    待机 (S2)
        系统固件不支持此待机状态。
    待机 (S3)
        当支持 S0 低电量待机时,禁用此待机状态。
    混合睡眠
        待机 (S3) 不可用。
        虚拟机监控程序不支持此待机状态。

关键信息:

  • S0 低电量待机:支持现代待机,网络保持连接
  • 休眠:支持完整休眠
  • S3:不支持传统睡眠(被 S0 替代)
  • 这是典型的新款笔记本配置

示例 2:台式机(支持传统睡眠)

方法一:使用 PowerShell 命令(推荐)_图2

此系统上有以下睡眠状态:
    待机 (S3)
    休眠
    混合睡眠
    快速启动
此系统上没有以下睡眠状态:
    待机 (S1)
        系统固件不支持此待机状态。
    待机 (S2)
        系统固件不支持此待机状态。
    待机 (S0 低电量待机)
        系统固件不支持此待机状态。

关键信息:

  • S3:支持传统睡眠
  • 混合睡眠:台式机默认模式
  • S0:不支持现代待机
  • 这是典型的台式机/老款笔记本配置

方法二:查看当前电源计划设置

# 查看当前活动的电源计划
powercfg /getactivescheme
# 查看详细的电源设置
powercfg /query

方法二:查看当前电源计划设置

方法三:图形界面查看

控制面板 → 硬件和声音 → 电源选项 → 更改计划设置 → 更改高级电源设置

展开 “睡眠” 选项,查看可用的设置项。

方法三:图形界面查看

台式机与笔记本的差异

对比表格

特性台式机(典型配置)笔记本(现代配置)
默认睡眠模式S3 传统睡眠 + 混合睡眠S0 现代待机
网络保持连接断开保持(Connected Standby)
程序后台运行完全暂停部分程序可以运行
唤醒速度中等(2-5秒)极快(<1秒)
功耗极低
硬件要求高(需要特定芯片组支持)

为什么笔记本可以保持部分功能运行?

现代笔记本的 S0 Modern Standby 采用了类似智能手机的电源管理策略:

网络栈保持活跃

  • Wi-Fi/蓝牙适配器保持低功耗工作
  • TCP 连接不会断开
  • 远程桌面(如向日葵、TeamViewer)可以唤醒系统

应用白名单机制

  • 系统级服务可以运行
  • 注册为后台任务的应用可以定期唤醒
  • UWP 应用支持后台运行

智能唤醒

  • 网络数据包可以唤醒系统
  • 定时任务可以唤醒系统
  • 硬件事件可以唤醒系统

解决方案

方案一:系统设置方式

1. 禁用自动睡眠(简单直接)

通过设置应用:

设置 → 系统 → 电源 → 屏幕和睡眠 → 根据需要设置

方案一:系统设置方式

通过控制面板:

控制面板 → 电源选项 → 编辑计划设置
- "使计算机进入睡眠状态" → 从不
- "更改高级电源设置"
  → 睡眠 → 在此时间后睡眠 → 0(从不)
  → 睡眠 → 在此时间后休眠 → 0(从不)

方案一:系统设置方式_图2

通过命令行:

方案一:系统设置方式_图3

2. 完全禁用休眠功能

# 以管理员身份运行
powercfg /h off

效果:

删除 C:\hiberfil.sys 文件(释放磁盘空间) 电源选项中不再有休眠选项 无法进入休眠状态

恢复方法:

powercfg /h on

3. 禁用混合睡眠(仅台式机)

控制面板 → 电源选项 → 更改计划设置 → 更改高级电源设置 → 睡眠 → 允许混合睡眠 → 关闭

方案一:系统设置方式_图4

4. 使用高性能电源计划

# 列出所有电源计划
powercfg /list
# 切换到高性能计划
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

优点:

操作简单,无需编程 系统级别的设置,对所有程序有效

缺点:

24小时不休眠,耗电量大 需要手动更改系统设置 可能忘记在不使用时恢复省电模式

方案一:系统设置方式_图5

方案二:程序级防休眠(推荐)

通过调用 Windows API,让程序运行时临时阻止系统休眠,程序退出后自动恢复正常电源管理。

核心 API:SetThreadExecutionState

EXECUTION_STATE SetThreadExecutionState(
  EXECUTION_STATE esFlags
);

参数说明:

标志说明
ES_CONTINUOUS0x80000000持续生效(直到清除或程序退出)
ES_SYSTEM_REQUIRED0x00000001阻止系统自动睡眠
ES_DISPLAY_REQUIRED0x00000002阻止显示器自动关闭
ES_AWAYMODE_REQUIRED0x00000040启用离开模式(媒体播放器专用)

组合使用:

// 阻止系统睡眠,允许显示器关闭
ES_CONTINUOUS | ES_SYSTEM_REQUIRED

// 阻止系统睡眠,同时保持显示器开启
ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED

// 恢复正常电源管理
ES_CONTINUOUS

工作原理:

程序调用 API 设置执行状态标志 Windows 电源管理器检测到标志后不会自动进入睡眠 用户手动触发的睡眠操作(如按电源键)仍然有效 程序退出时系统自动清除标志 如果程序崩溃,系统也会自动清除(安全机制)

优点:

  • 不影响系统设置,程序退出后自动恢复
  • 支持 S0、S3 等所有睡眠模式
  • 不需要管理员权限
  • 用户仍可以手动控制电源

缺点:

  • 需要编程实现
  • 仅在程序运行时有效

代码实现

C# 版本

基础版本(支持显示器控制)

using System;
using System.Runtime.InteropServices;
namespace PowerManagement
{
    /// <summary>系统睡眠状态控制类</summary>
    /// <remarks>
    /// <para>功能说明:</para>
    /// <para>通过调用 Windows Kernel32 API 控制系统电源管理行为,防止系统在程序运行期间自动进入睡眠或休眠状态。</para>
    /// <para>主要用于需要长时间持续运行的工业控制程序,避免因系统睡眠导致:</para>
    /// <list type="number">
    /// <item>PLC 通信连接断开</item>
    /// <item>设备控制序列中断</item>
    /// <item>实时监控数据丢失</item>
    /// <item>远程连接异常</item>
    /// </list>
    /// <para>技术说明:</para>
    /// <para>- 使用 SetThreadExecutionState API 设置线程执行状态标志</para>
    /// <para>- ES_CONTINUOUS 标志确保设置持续有效直到显式清除</para>
    /// <para>- ES_SYSTEM_REQUIRED 标志阻止系统自动进入睡眠模式</para>
    /// <para>- 程序异常退出时系统会自动清除标志,恢复正常电源管理</para>
    /// <para>应用场景:</para>
    /// <para>适用于台式机的传统 S3 睡眠模式和笔记本的现代 S0 待机模式,但不阻止用户手动触发的睡眠操作。</para>
    /// </remarks>
    public class SleepPreventer
    {
        /// <summary>阻止系统睡眠的工作模式</summary>
        public enum PreventMode
        {
            /// <summary>仅阻止系统睡眠,允许显示器关闭</summary>
            /// <remarks>适用场景:后台服务、无界面程序、允许显示器省电的情况</remarks>
            SystemOnly,
            /// <summary>阻止系统睡眠且保持显示器开启</summary>
            /// <remarks>适用场景:监控界面、远程桌面、需要持续显示的应用</remarks>
            SystemAndDisplay
        }
        /// <summary>设置线程执行状态的 Windows API</summary>
        /// <param name="esFlags">执行状态标志的组合值</param>
        /// <returns>返回之前的线程执行状态标志。</returns>
        /// <remarks>此 API 位于 kernel32.dll 中,用于通知系统当前线程正在执行关键操作,需要保持系统活动状态。</remarks>
        [DllImport("kernel32.dll")]
        static extern uint SetThreadExecutionState(uint esFlags);
        /// <summary>执行状态持续标志</summary>
        /// <remarks>
        /// 值:0x80000000
        /// <para>表示执行状态设置持续有效,直到下一次调用 SetThreadExecutionState 清除或程序终止。</para>
        /// <para>必须与 ES_SYSTEM_REQUIRED 或 ES_DISPLAY_REQUIRED 组合使用。</para>
        /// </remarks>
        const uint ES_CONTINUOUS = 0x80000000;
        /// <summary>系统必需标志</summary>
        /// <remarks>
        /// 值:0x00000001
        /// <para>通知系统当前线程需要系统保持活动状态。</para>
        /// <para>防止系统自动进入睡眠模式,但允许显示器关闭。</para>
        /// </remarks>
        const uint ES_SYSTEM_REQUIRED = 0x00000001;
        /// <summary>显示器必需标志</summary>
        /// <remarks>
        /// 值:0x00000002
        /// <para>通知系统当前线程需要显示器保持开启状态。</para>
        /// <para>防止显示器自动关闭,同时也阻止系统进入睡眠模式。</para>
        /// <para>注意:未在当前实现中使用,如需保持显示器开启可在 <see cref="PreventSleep"/> 方法中添加此标志。</para>
        /// </remarks>
        const uint ES_DISPLAY_REQUIRED = 0x00000002;
        /// <summary>阻止系统自动进入睡眠状态</summary>
        /// <param name="mode">防休眠模式</param>
        /// <returns>操作是否成功</returns>
        /// <remarks>
        /// <para>执行流程:</para>
        /// <list type="number">
        /// <item>调用 SetThreadExecutionState API 设置执行状态标志</item>
        /// <item>组合 ES_CONTINUOUS 和 ES_SYSTEM_REQUIRED 标志</item>
        /// <item>持续阻止系统自动睡眠,直到调用 <see cref="AllowSleep"/> 或程序终止</item>
        /// </list>
        /// <para>注意事项:</para>
        /// <para>- 仅阻止系统<b>自动</b>睡眠,不影响用户手动触发的睡眠操作</para>
        /// <para>- 显示器仍可能自动关闭(如需保持显示器开启,需添加 ES_DISPLAY_REQUIRED 标志)</para>
        /// <para>- 建议在程序主入口点或服务启动时调用</para>
        /// <para>- 程序崩溃或异常退出时,系统会自动清除此设置</para>
        /// <para>应用建议:</para>
        /// <para>适用于需要长时间连续运行的场景,如 PLC 通信监控、设备控制序列执行、数据采集等。</para>
        /// </remarks>
        /// <example>
        /// 在程序启动时调用:
        /// <code>
        /// public static void Main()
        /// {
        ///     SleepPreventer.PreventSleep();
        ///     // ... 程序主逻辑
        /// }
        /// </code>
        /// </example>
        public static bool PreventSleep(PreventMode mode = PreventMode.SystemOnly)
        {
            uint flags = ES_CONTINUOUS | ES_SYSTEM_REQUIRED;
            if (mode == PreventMode.SystemAndDisplay)
            {
                flags |= ES_DISPLAY_REQUIRED;
            }
            uint result = SetThreadExecutionState(flags);
            return result != 0;
        }
        /// <summary>恢复系统正常电源管理行为</summary>
        /// <remarks>
        /// <para>执行流程:</para>
        /// <list type="number">
        /// <item>调用 SetThreadExecutionState API 并仅传入 ES_CONTINUOUS 标志</item>
        /// <item>清除之前设置的 ES_SYSTEM_REQUIRED 标志</item>
        /// <item>系统恢复正常的自动睡眠行为</item>
        /// </list>
        /// <para>注意事项:</para>
        /// <para>- 建议在程序正常退出前调用,确保不影响系统的电源管理</para>
        /// <para>- 如果程序异常终止未调用此方法,系统会自动清除执行状态设置</para>
        /// <para>- 调用后系统将按照电源计划设置的时间自动进入睡眠</para>
        /// <para>应用建议:</para>
        /// <para>在程序关闭事件、服务停止事件或 Dispose 方法中调用此方法。</para>
        /// </remarks>
        /// <example>
        /// 在程序退出时调用:
        /// <code>
        /// protected override void OnClosed(EventArgs e)
        /// {
        ///     SleepPreventer.AllowSleep();
        ///     base.OnClosed(e);
        /// }
        /// </code>
        /// </example>
        public static void AllowSleep()
        {
            SetThreadExecutionState(ES_CONTINUOUS);
        }
    }
}

使用示例

WinForms 应用程序:

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        // 窗口加载时阻止休眠
        this.Load += (s, e) => SleepPreventer.PreventSleep();
        // 窗口关闭时恢复
        this.FormClosing += (s, e) => SleepPreventer.AllowSleep();
    }
}

WPF 应用程序:

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        // 程序启动时阻止休眠
        SleepPreventer.PreventSleep();
    }
    protected override void OnExit(ExitEventArgs e)
    {
        // 程序退出时恢复
        SleepPreventer.AllowSleep();
        base.OnExit(e);
    }
}

控制台应用程序:

class Program
{
    static void Main(string[] args)
    {
        // 阻止休眠
        SleepPreventer.PreventSleep();
        Console.WriteLine("程序运行中,系统不会自动睡眠...");
        Console.WriteLine("按任意键退出");
        // 业务逻辑
        DoWork();
        Console.ReadKey();
        // 恢复正常
        SleepPreventer.AllowSleep();
    }
    static void DoWork()
    {
        // 长时间运行的任务
        while (true)
        {
            // PLC 通信、数据采集等
            Thread.Sleep(1000);
        }
    }
}

Windows 服务:

public partial class MyService : ServiceBase
{
    protected override void OnStart(string[] args)
    {
        // 服务启动时阻止休眠
        SleepPreventer.PreventSleep();
        // 启动业务逻辑
        StartWorkThread();
    }
    protected override void OnStop()
    {
        // 服务停止时恢复
        SleepPreventer.AllowSleep();
        // 停止业务逻辑
        StopWorkThread();
    }
}

C++ 版本

基础版本

// SleepPreventer.h
#ifndef SLEEP_PREVENTER_H
#define SLEEP_PREVENTER_H
#include <windows.h>
/**
 * @brief 系统睡眠状态控制类
 * 
 * 通过调用 Windows API 控制系统电源管理行为,防止系统在程序运行期间
 * 自动进入睡眠或休眠状态。
 * 
 * 主要用于需要长时间持续运行的工业控制程序,避免因系统睡眠导致:
 * - PLC 通信连接断开
 * - 设备控制序列中断
 * - 实时监控数据丢失
 * - 远程连接异常
 * 
 * @note 适用于 Windows XP SP1 及以上版本
 */
class SleepPreventer
{
public:
    /**
     * @brief 阻止系统自动进入睡眠状态
     * 
     * 执行流程:
     * 1. 调用 SetThreadExecutionState API 设置执行状态标志
     * 2. 组合 ES_CONTINUOUS 和 ES_SYSTEM_REQUIRED 标志
     * 3. 持续阻止系统自动睡眠,直到调用 AllowSleep() 或程序终止
     * 
     * @note 仅阻止系统自动睡眠,不影响用户手动触发的睡眠操作
     * @note 显示器仍可能自动关闭(如需保持显示器开启,调用 PreventSleepAndDisplay())
     * @note 程序崩溃或异常退出时,系统会自动清除此设置
     * 
     * @return 成功返回 true,失败返回 false
     * 
     * @example
     * @code
     * int main()
     * {
     *     SleepPreventer::PreventSleep();
     *     
     *     // 你的业务逻辑
     *     DoWork();
     *     
     *     SleepPreventer::AllowSleep();
     *     return 0;
     * }
     * @endcode
     */
    static bool PreventSleep();
    /**
     * @brief 阻止系统睡眠并保持显示器开启
     * 
     * 相比 PreventSleep(),此方法同时保持显示器开启状态。
     * 适用于需要持续显示界面的应用程序(如监控系统、远程桌面等)。
     * 
     * @return 成功返回 true,失败返回 false
     * 
     * @example
     * @code
     * // 用于监控界面,保持屏幕常亮
     * SleepPreventer::PreventSleepAndDisplay();
     * @endcode
     */
    static bool PreventSleepAndDisplay();
    /**
     * @brief 恢复系统正常电源管理行为
     * 
     * 执行流程:
     * 1. 调用 SetThreadExecutionState API 并仅传入 ES_CONTINUOUS 标志
     * 2. 清除之前设置的 ES_SYSTEM_REQUIRED 标志
     * 3. 系统恢复正常的自动睡眠行为
     * 
     * @note 建议在程序正常退出前调用,确保不影响系统的电源管理
     * @note 如果程序异常终止未调用此方法,系统会自动清除执行状态设置
     * 
     * @return 成功返回 true,失败返回 false
     */
    static bool AllowSleep();
private:
    /// 执行状态持续标志(0x80000000)
    static const DWORD ES_CONTINUOUS = 0x80000000;
    /// 系统必需标志(0x00000001)- 阻止系统睡眠
    static const DWORD ES_SYSTEM_REQUIRED = 0x00000001;
    /// 显示器必需标志(0x00000002)- 保持显示器开启
    static const DWORD ES_DISPLAY_REQUIRED = 0x00000002;
};
#endif // SLEEP_PREVENTER_H
// SleepPreventer.cpp
#include "SleepPreventer.h"
bool SleepPreventer::PreventSleep()
{
    EXECUTION_STATE result = SetThreadExecutionState(
        ES_CONTINUOUS | ES_SYSTEM_REQUIRED
    );
    // SetThreadExecutionState 返回之前的状态,返回 0 表示失败
    return (result != 0);
}
bool SleepPreventer::PreventSleepAndDisplay()
{
    EXECUTION_STATE result = SetThreadExecutionState(
        ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED
    );
    return (result != 0);
}
bool SleepPreventer::AllowSleep()
{
    EXECUTION_STATE result = SetThreadExecutionState(ES_CONTINUOUS);
    return (result != 0);
}

面向对象版本(RAII 自动管理)

// SleepPreventerRAII.h
#ifndef SLEEP_PREVENTER_RAII_H
#define SLEEP_PREVENTER_RAII_H
#include <windows.h>
/**
 * @brief RAII 风格的睡眠防护类
 * 
 * 使用 RAII(Resource Acquisition Is Initialization)模式自动管理
 * 睡眠防护的生命周期:
 * - 构造函数:自动阻止系统睡眠
 * - 析构函数:自动恢复正常电源管理
 * 
 * 这种方式确保即使发生异常,也能正确恢复系统电源设置。
 * 
 * @example
 * @code
 * void DoLongRunningTask()
 * {
 *     // 创建对象时自动阻止睡眠
 *     SleepPreventerRAII preventer;
 *     
 *     // 执行长时间任务
 *     ProcessData();
 *     CommunicateWithPLC();
 *     
 *     // 函数返回时自动析构,恢复电源管理
 * }
 * @endcode
 */
class SleepPreventerRAII
{
public:
    /**
     * @brief 防休眠模式枚举
     */
    enum class Mode
    {
        SystemOnly,         ///< 仅阻止系统睡眠,允许显示器关闭
        SystemAndDisplay    ///< 阻止系统睡眠且保持显示器开启
    };
    /**
     * @brief 构造函数 - 自动阻止系统睡眠
     * 
     * @param mode 防休眠模式
     */
    explicit SleepPreventerRAII(Mode mode = Mode::SystemOnly);
    /**
     * @brief 析构函数 - 自动恢复正常电源管理
     */
    ~SleepPreventerRAII();
    // 禁止拷贝和赋值
    SleepPreventerRAII(const SleepPreventerRAII&) = delete;
    SleepPreventerRAII& operator=(const SleepPreventerRAII&) = delete;
    /**
     * @brief 检查是否成功设置防休眠
     * 
     * @return 成功返回 true,失败返回 false
     */
    bool IsActive() const { return m_isActive; }
private:
    bool m_isActive;                    ///< 是否已成功激活防休眠
    EXECUTION_STATE m_previousState;    ///< 保存之前的执行状态
    static const DWORD ES_CONTINUOUS = 0x80000000;
    static const DWORD ES_SYSTEM_REQUIRED = 0x00000001;
    static const DWORD ES_DISPLAY_REQUIRED = 0x00000002;
};
#endif // SLEEP_PREVENTER_RAII_H
// SleepPreventerRAII.cpp
#include "SleepPreventerRAII.h"
SleepPreventerRAII::SleepPreventerRAII(Mode mode)
    : m_isActive(false)
    , m_previousState(0)
{
    DWORD flags = ES_CONTINUOUS | ES_SYSTEM_REQUIRED;
    if (mode == Mode::SystemAndDisplay)
    {
        flags |= ES_DISPLAY_REQUIRED;
    }
    m_previousState = SetThreadExecutionState(flags);
    m_isActive = (m_previousState != 0);
}
SleepPreventerRAII::~SleepPreventerRAII()
{
    if (m_isActive)
    {
        // 恢复正常电源管理
        SetThreadExecutionState(ES_CONTINUOUS);
    }
}

使用示例

控制台应用程序:

#include <iostream>
#include <thread>
#include <chrono>
#include "SleepPreventer.h"
int main()
{
    std::cout << "程序启动,阻止系统睡眠..." << std::endl;
    // 阻止系统睡眠
    if (!SleepPreventer::PreventSleep())
    {
        std::cerr << "警告:无法阻止系统睡眠!" << std::endl;
    }
    // 模拟长时间运行的任务
    for (int i = 0; i < 60; ++i)
    {
        std::cout << "运行中... " << i << " 秒" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    // 恢复正常电源管理
    SleepPreventer::AllowSleep();
    std::cout << "任务完成,恢复正常电源管理" << std::endl;
    return 0;
}

使用 RAII 版本:

#include <iostream>
#include "SleepPreventerRAII.h"
void ProcessData()
{
    // 使用 RAII,自动管理生命周期
    SleepPreventerRAII preventer(SleepPreventerRAII::Mode::SystemOnly);
    if (!preventer.IsActive())
    {
        std::cerr << "警告:无法阻止系统睡眠!" << std::endl;
    }
    std::cout << "开始数据处理..." << std::endl;
    // 执行长时间任务
    // ... 你的业务逻辑 ...
    std::cout << "数据处理完成" << std::endl;
    // 函数返回时自动恢复电源管理(析构函数调用)
}
int main()
{
    ProcessData();
    return 0;
}

Qt 应用程序:

// MainWindow.h
#include <QMainWindow>
#include "SleepPreventer.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
protected:
    void showEvent(QShowEvent *event) override;
    void closeEvent(QCloseEvent *event) override;
private:
    bool m_sleepPrevented;
};
// MainWindow.cpp
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , m_sleepPrevented(false)
{
}
MainWindow::~MainWindow()
{
    if (m_sleepPrevented)
    {
        SleepPreventer::AllowSleep();
    }
}
void MainWindow::showEvent(QShowEvent *event)
{
    QMainWindow::showEvent(event);
    // 窗口显示时阻止睡眠
    if (SleepPreventer::PreventSleepAndDisplay())
    {
        m_sleepPrevented = true;
        qDebug() << "已阻止系统睡眠";
    }
}
void MainWindow::closeEvent(QCloseEvent *event)
{
    // 窗口关闭时恢复
    if (m_sleepPrevented)
    {
        SleepPreventer::AllowSleep();
        m_sleepPrevented = false;
        qDebug() << "已恢复正常电源管理";
    }
    QMainWindow::closeEvent(event);
}

MFC 应用程序:

// MainDlg.cpp
#include "SleepPreventer.h"
BOOL CMainDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
    // 对话框初始化时阻止睡眠
    if (SleepPreventer::PreventSleep())
    {
        TRACE(_T("已阻止系统睡眠\n"));
    }
    else
    {
        AfxMessageBox(_T("警告:无法阻止系统睡眠!"));
    }
    return TRUE;
}
void CMainDlg::OnDestroy()
{
    // 对话框销毁时恢复
    SleepPreventer::AllowSleep();
    TRACE(_T("已恢复正常电源管理\n"));
    CDialogEx::OnDestroy();
}

常见问题解答

Q1: 为什么笔记本合盖后程序还能运行,但台式机睡眠后就不行?

A: 因为两者使用的睡眠技术不同:

笔记本(S0 Modern Standby)

  • 保持网络连接(Connected Standby)
  • 向日葵等软件可以通过网络唤醒系统
  • 类似手机的"息屏"状态

台式机(S3 传统睡眠)

  • 网络适配器断电,连接断开
  • 无法通过网络唤醒(除非配置 WOL)
  • 所有用户程序暂停

解决方案:

  • 台式机:使用本文提供的 SleepPreventer 类
  • 或配置 Wake-on-LAN(需要主板和网卡支持)

Q2: SetThreadExecutionState 会影响用户手动睡眠操作吗?

A:不会。此 API 只阻止系统自动进入睡眠,不影响用户主动操作:

  • 用户点击"开始菜单 → 睡眠"仍然有效
  • 笔记本合盖仍会睡眠(根据电源设置)
  • 按电源键的行为由 BIOS/系统设置决定
  • 不会阻止用户手动触发的睡眠

这是 Windows 设计的安全机制,确保用户始终有最高控制权。

Q3: 程序崩溃或被强制结束,系统会一直不睡眠吗?

A:不会。Windows 有安全机制:

  • 程序进程终止时,系统自动清除所有执行状态标志
  • 即使程序崩溃、被杀进程、蓝屏,系统都会恢复正常
  • 不需要担心"忘记调用 AllowSleep"会导致系统永久不睡眠

建议:

  • 仍应在程序退出时主动调用 AllowSleep()
  • 这是良好的编程习惯,体现对系统资源的尊重

主动调用 AllowSleep() 这是良好的编程习惯,体现对系统资源的尊重

Q4: 为什么有时候设置了还是会睡眠?

可能的原因:

API 调用失败

// 检查返回值
uint result = SetThreadExecutionState(...);
if (result == 0)
{
    // 失败,获取错误码
    int error = Marshal.GetLastWin32Error();
}

标志设置不正确

  • 必须包含 ES_CONTINUOUS
  • 必须包含 ES_SYSTEM_REQUIRED 或 ES_DISPLAY_REQUIRED

被其他程序或策略覆盖

  • 组策略禁用了应用程序阻止睡眠
  • 其他程序调用了相同的 API

电源按钮被按下

  • 用户主动操作优先级最高

调试方法:

# 查看哪些程序正在阻止睡眠
powercfg /requests

输出示例:

DISPLAY:
[PROCESS] \Device\HarddiskVolume3\Program Files\MyApp\MyApp.exe

SYSTEM:
[PROCESS] \Device\HarddiskVolume3\Program Files\MyApp\MyApp.exe

Q4: 为什么有时候设置了还是会睡眠?

Q5: 是否需要管理员权限?

A:不需要。SetThreadExecutionState 是用户级 API:

  • 普通用户权限即可调用
  • 不需要提升权限(UAC)
  • 可以在任何应用程序类型中使用

但是修改系统电源设置需要管理员权限:

# 需要管理员权限
powercfg /h off
powercfg /change standby-timeout-ac 0

Q6: 对笔记本电池有影响吗?

A: 有一定影响,取决于使用方式:

场景影响建议
接通电源无影响正常使用
使用电池电池消耗加快谨慎使用,建议接通电源
仅阻止系统睡眠影响较小可接受
同时保持显示器开启影响较大尽量避免

节能建议:

// 检测电源状态
if (SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online)
{
    // 接通电源,阻止睡眠
    SleepPreventer.PreventSleep();
}
else
{
    // 使用电池,允许睡眠以节能
    SleepPreventer.AllowSleep();
}

Q7: 支持哪些 Windows 版本?

A:SetThreadExecutionState API 支持:

  • Windows XP SP1 及以上
  • Windows Vista/7/8/8.1/10/11
  • Windows Server 2003 及以上

兼容性非常好,几乎所有现代 Windows 系统都支持。

Q8: 如何在多线程环境中使用?

A:SetThreadExecutionState 是线程局部的,但标志是全局共享的:

// 错误示例:多个线程同时设置可能冲突
Thread thread1 = new Thread(() => {
    SleepPreventer.PreventSleep();
    DoWork1();
    SleepPreventer.AllowSleep(); // ⚠️ 会影响其他线程
});
Thread thread2 = new Thread(() => {
    SleepPreventer.PreventSleep();
    DoWork2();
    // thread1 调用 AllowSleep 后,这里的设置会被清除
});

推荐方案:

// 在主线程统一管理
public class PowerManager
{
    private static int _preventCount = 0;
    private static readonly object _lock = new object();
    public static void PreventSleep()
    {
        lock (_lock)
        {
            if (_preventCount == 0)
            {
                SetThreadExecutionState(
                    ES_CONTINUOUS | ES_SYSTEM_REQUIRED
                );
            }
            _preventCount++;
        }
    }
    public static void AllowSleep()
    {
        lock (_lock)
        {
            _preventCount--;
            if (_preventCount <= 0)
            {
                _preventCount = 0;
                SetThreadExecutionState(ES_CONTINUOUS);
            }
        }
    }
}

Q9: 与其他电源管理工具冲突吗?

A: 一般不会,但有特殊情况:

兼容的工具:

  • Caffeine
  • Don’t Sleep
  • PowerToys (Awake 模块)
  • 游戏模式
  • Windows 焦点辅助

可能冲突的情况:

  • 组策略强制睡眠设置
  • 企业设备管理策略
  • BIOS 级别的电源管理

检查方法:

# 查看活动的电源请求
powercfg /requests
# 查看组策略设置
gpedit.msc → 计算机配置 → 管理模板 → 系统 → 电源管理

Q10: 远程桌面断开后,程序会睡眠吗?

A: 取决于系统配置:

Windows 10/11 默认行为:

  • 远程桌面断开后,服务器不会自动睡眠
  • 但会关闭显示器(除非设置了 ES_DISPLAY_REQUIRED)

如果需要保持远程可用:

// 保持显示器开启,确保远程桌面可用
SleepPreventer.PreventSleep(SleepPreventer.PreventMode.SystemAndDisplay);

组策略设置:

gpedit.msc → 计算机配置 → 管理模板 → Windows 组件 → 远程桌面服务
→ 远程桌面会话主机 → 连接 → "允许用户通过使用远程桌面服务远程连接" → 已启用

总结

关键要点

理解不同的睡眠模式

  • S0 Modern Standby(笔记本):保持网络,部分程序可运行
  • S3 传统睡眠(台式机):暂停所有程序,断开网络
  • S4 休眠:完全断电,所有程序停止

选择合适的解决方案

  • 临时测试:系统设置禁用睡眠
  • 生产环境:程序级防休眠(推荐)
  • 服务器:完全禁用休眠功能

程序级防休眠优势

  • 不影响系统设置
  • 程序退出自动恢复
  • 用户仍可手动控制
  • 无需管理员权限

最佳实践

  • 在程序启动时调用 PreventSleep()
  • 在程序退出时调用 AllowSleep()
  • 根据场景选择是否保持显示器开启
  • 考虑笔记本电池使用情况

代码使用建议

应用类型推荐模式说明
后台服务SystemOnly允许显示器关闭以节能
监控界面SystemAndDisplay保持屏幕显示
数据采集SystemOnly无界面程序
远程控制SystemAndDisplay确保远程可用
工业控制SystemOnly保持 PLC 通信

以上就是Windows系统进入了休眠或睡眠状态怎么办?如何解决的详细内容,更多相关资料请阅读主机测评网其它文章!

本文由主机测评网发布,不代表主机测评网立场,转载联系作者并注明出处:https://zhuji.jb51.net/windows/8829.html

联系我们

在线咨询:点击这里给我发消息

Q Q:2220678578