Windows系统进入了休眠或睡眠状态怎么办?如何解决?一文详解
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>Windows 11 休眠问题深度解析与解决方案<ul class="second_class_ul"><li>问题背景</li><li>Windows 电源管理机制详解</li><ul class="third_class_ul"><li>1. 睡眠模式(Sleep / S3)</li><li>2. 休眠模式(Hibernate / S4)</li><li>3. 混合睡眠(Hybrid Sleep)</li><li>4. 快速启动(Fast Startup)</li></ul><li>如何查看系统支持的休眠模式</li><ul class="third_class_ul"><li>方法一:使用 PowerShell 命令(推荐)</li><li>方法二:查看当前电源计划设置</li><li>方法三:图形界面查看</li></ul><li>台式机与笔记本的差异</li><ul class="third_class_ul"><li>对比表格</li><li>为什么笔记本可以保持部分功能运行?</li></ul><li>解决方案</li><ul class="third_class_ul"><li>方案一:系统设置方式</li><li>方案二:程序级防休眠(推荐)</li></ul><li>代码实现</li><ul class="third_class_ul"><li>C# 版本</li><li>C++ 版本</li></ul><li>常见问题解答</li><ul class="third_class_ul"><li>Q1: 为什么笔记本合盖后程序还能运行,但台式机睡眠后就不行?</li><li>Q2: SetThreadExecutionState 会影响用户手动睡眠操作吗?</li><li>Q3: 程序崩溃或被强制结束,系统会一直不睡眠吗?</li><li>Q4: 为什么有时候设置了还是会睡眠?</li><li>Q5: 是否需要管理员权限?</li><li>Q6: 对笔记本电池有影响吗?</li><li>Q7: 支持哪些 Windows 版本?</li><li>Q8: 如何在多线程环境中使用?</li><li>Q9: 与其他电源管理工具冲突吗?</li><li>Q10: 远程桌面断开后,程序会睡眠吗?</li></ul><li>总结</li><ul class="third_class_ul"><li>关键要点</li><li>代码使用建议</li></ul></ul></li></ul></div><p class="maodian"></p><h2>Windows 11 休眠问题深度解析与解决方案</h2><p class="maodian"></p><h3>问题背景</h3>
<p>在开发需要长时间持续运行的应用程序时(如工业控制软件、PLC 通信程序、数据采集系统等),经常会遇到以下问题:</p>
<ul><li>程序运行一段时间后自动停止响应</li><li>设备通信连接突然断开</li><li>远程连接无法访问</li><li>定时任务没有执行</li></ul>
<p><strong>根本原因</strong>:Windows 系统进入了休眠或睡眠状态,导致程序暂停或终止运行。</p>
<p class="maodian"></p><h3>Windows 电源管理机制详解</h3>
<p>Windows 提供了多种省电模式,每种模式对程序运行的影响各不相同:</p>
<p class="maodian"></p><h4>1. 睡眠模式(Sleep / S3)</h4>
<p><strong>传统睡眠状态(S3)</strong></p>
<p><strong>工作原理</strong>:</p>
<ul><li>CPU 进入低功耗状态</li><li>内存(RAM)保持供电,数据保留</li><li>硬盘、网络等外设断电</li><li>显示器关闭</li></ul>
<p><strong>对程序的影响</strong>:</p>
<ul><li>用户程序暂停执行</li><li>网络连接断开</li><li>USB 设备可能断电</li><li>唤醒后可以恢复</li></ul>
<p><strong>适用场景</strong>:</p>
<ul><li>短时间离开(几分钟到几小时)</li><li>需要快速恢复工作</li></ul>
<p><strong>现代待机(Modern Standby / S0)</strong></p>
<p><strong>工作原理</strong>:</p>
<ul><li>CPU 保持极低功耗运行</li><li>内存持续供电</li><li><strong>保持网络连接</strong>(Connected Standby)</li><li>特定应用可以后台运行</li></ul>
<p><strong>对程序的影响</strong>:</p>
<ul><li>特定程序可以继续运行</li><li>网络保持连接</li><li>推送通知正常工作</li><li>非白名单程序仍会暂停</li></ul>
<p><strong>适用场景</strong>:</p>
<ul><li>笔记本合盖</li><li>类似手机的"息屏"状态</li></ul>
<p class="maodian"></p><h4>2. 休眠模式(Hibernate / S4)</h4>
<p><strong>工作原理</strong>:</p>
<ul><li>将内存数据完整写入硬盘(hiberfil.sys)</li><li>CPU、内存、所有外设完全断电</li><li>相当于"关机 + 保存状态"</li></ul>
<p><strong>对程序的影响</strong>:</p>
<ul><li>所有程序完全停止</li><li>网络连接断开</li><li>所有硬件停止工作</li><li>唤醒后恢复到之前状态</li></ul>
<p><strong>适用场景</strong>:</p>
<ul><li>长时间不使用(数小时到数天)</li><li>笔记本电量耗尽时自动进入</li></ul>
<p class="maodian"></p><h4>3. 混合睡眠(Hybrid Sleep)</h4>
<p><strong>工作原理</strong>:</p>
<ul><li>结合睡眠和休眠的特点</li><li>内存保持供电的同时,也将数据写入硬盘</li><li>正常情况下像睡眠一样快速唤醒</li><li>意外断电时可以从硬盘恢复</li></ul>
<p><strong>对程序的影响</strong>:</p>
<ul><li>类似传统睡眠(S3)</li><li>台式机默认开启</li></ul>
<p class="maodian"></p><h4>4. 快速启动(Fast Startup)</h4>
<p><strong>工作原理</strong>:</p>
<ul><li>关机时保存系统内核状态到硬盘</li><li>下次开机时快速加载</li><li>用户会话不保存</li></ul>
<p><strong>对程序的影响</strong>:</p>
<ul><li>程序完全关闭</li><li>不影响正常运行</li></ul>
<p class="maodian"></p><h3>如何查看系统支持的休眠模式</h3>
<p class="maodian"></p><h4>方法一:使用 PowerShell 命令(推荐)</h4>
<p>打开 <strong>PowerShell</strong> 或 <strong>命令提示符</strong>,输入:</p>
<div class="dxycode"><pre class="brush:bash;">powercfg /a</pre></div>
<p><strong>输出示例解读:</strong></p>
<p>示例 1:笔记本(支持现代待机)</p>
<p><img alt="方法一:使用 PowerShell 命令(推荐)" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04KD.png" /></p>
<div class="dxycode"><pre class="brush:bash;">此系统上有以下睡眠状态:
待机 (S0 低电量待机) 连接的网络
休眠
快速启动
此系统上没有以下睡眠状态:
待机 (S1)
系统固件不支持此待机状态。
待机 (S2)
系统固件不支持此待机状态。
待机 (S3)
当支持 S0 低电量待机时,禁用此待机状态。
混合睡眠
待机 (S3) 不可用。
虚拟机监控程序不支持此待机状态。</pre></div>
<p><strong>关键信息:</strong></p>
<ul><li><strong>S0 低电量待机</strong>:支持现代待机,网络保持连接</li><li><strong>休眠</strong>:支持完整休眠</li><li><strong>S3</strong>:不支持传统睡眠(被 S0 替代)</li><li>这是典型的<strong>新款笔记本</strong>配置</li></ul>
<p>示例 2:台式机(支持传统睡眠)</p>
<p><img alt="方法一:使用 PowerShell 命令(推荐)_图2" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04H19.png" /></p>
<div class="dxycode"><pre class="brush:bash;">此系统上有以下睡眠状态:
待机 (S3)
休眠
混合睡眠
快速启动
此系统上没有以下睡眠状态:
待机 (S1)
系统固件不支持此待机状态。
待机 (S2)
系统固件不支持此待机状态。
待机 (S0 低电量待机)
系统固件不支持此待机状态。</pre></div>
<p><strong>关键信息:</strong></p>
<ul><li><strong>S3</strong>:支持传统睡眠</li><li><strong>混合睡眠</strong>:台式机默认模式</li><li><strong>S0</strong>:不支持现代待机</li><li>这是典型的<strong>台式机/老款笔记本</strong>配置</li></ul>
<p class="maodian"></p><h4>方法二:查看当前电源计划设置</h4>
<div class="dxycode"><pre class="brush:bash;"># 查看当前活动的电源计划
powercfg /getactivescheme
# 查看详细的电源设置
powercfg /query</pre></div>
<p><img alt="方法二:查看当前电源计划设置" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04G07.png" /></p>
<p class="maodian"></p><h4>方法三:图形界面查看</h4>
<div class="dxycode"><pre class="brush:plain;">控制面板 → 硬件和声音 → 电源选项 → 更改计划设置 → 更改高级电源设置
</pre></div>
<p>展开 <strong>“睡眠”</strong> 选项,查看可用的设置项。</p>
<p><img alt="方法三:图形界面查看" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04M96.png" /></p>
<p class="maodian"></p><h3>台式机与笔记本的差异</h3>
<p class="maodian"></p><h4>对比表格</h4>
<table><tbody><tr><th style="text-align:center">特性</th><th style="text-align:center">台式机(典型配置)</th><th style="text-align:center">笔记本(现代配置)</th></tr><tr><td style="text-align:center"><strong>默认睡眠模式</strong></td><td style="text-align:center">S3 传统睡眠 + 混合睡眠</td><td style="text-align:center">S0 现代待机</td></tr><tr><td style="text-align:center"><strong>网络保持连接</strong></td><td style="text-align:center">断开</td><td style="text-align:center">保持(Connected Standby)</td></tr><tr><td style="text-align:center"><strong>程序后台运行</strong></td><td style="text-align:center">完全暂停</td><td style="text-align:center">部分程序可以运行</td></tr><tr><td style="text-align:center"><strong>唤醒速度</strong></td><td style="text-align:center">中等(2-5秒)</td><td style="text-align:center">极快(<1秒)</td></tr><tr><td style="text-align:center"><strong>功耗</strong></td><td style="text-align:center">低</td><td style="text-align:center">极低</td></tr><tr><td style="text-align:center"><strong>硬件要求</strong></td><td style="text-align:center">低</td><td style="text-align:center">高(需要特定芯片组支持)</td></tr></tbody></table>
<p class="maodian"></p><h4>为什么笔记本可以保持部分功能运行?</h4>
<p>现代笔记本的 <strong>S0 Modern Standby</strong> 采用了类似智能手机的电源管理策略:</p>
<p><strong>网络栈保持活跃</strong>:</p>
<ul><li>Wi-Fi/蓝牙适配器保持低功耗工作</li><li>TCP 连接不会断开</li><li>远程桌面(如向日葵、TeamViewer)可以唤醒系统</li></ul>
<p><strong>应用白名单机制</strong>:</p>
<ul><li>系统级服务可以运行</li><li>注册为后台任务的应用可以定期唤醒</li><li>UWP 应用支持后台运行</li></ul>
<p><strong>智能唤醒</strong>:</p>
<ul><li>网络数据包可以唤醒系统</li><li>定时任务可以唤醒系统</li><li>硬件事件可以唤醒系统</li></ul>
<p class="maodian"></p><h3>解决方案</h3>
<p class="maodian"></p><h4>方案一:系统设置方式</h4>
<p>1. 禁用自动睡眠(简单直接)</p>
<p><strong>通过设置应用:</strong></p>
<div class="dxycode"><pre class="brush:plain;">设置 → 系统 → 电源 → 屏幕和睡眠 → 根据需要设置
</pre></div>
<p><img alt="方案一:系统设置方式" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04HL.png" /></p>
<p><strong>通过控制面板:</strong></p>
<div class="dxycode"><pre class="brush:plain;">控制面板 → 电源选项 → 编辑计划设置
- "使计算机进入睡眠状态" → 从不
- "更改高级电源设置"
→ 睡眠 → 在此时间后睡眠 → 0(从不)
→ 睡眠 → 在此时间后休眠 → 0(从不)
</pre></div>
<p><img alt="方案一:系统设置方式_图2" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04I05.png" /></p>
<p><strong>通过命令行:</strong></p>
<p><img alt="方案一:系统设置方式_图3" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04S21.png" /></p>
<p>2. 完全禁用休眠功能</p>
<div class="dxycode"><pre class="brush:bash;"># 以管理员身份运行
powercfg /h off</pre></div>
<p><strong>效果:</strong></p>
<p>删除 C:\hiberfil.sys 文件(释放磁盘空间) 电源选项中不再有休眠选项 无法进入休眠状态</p>
<p><strong>恢复方法:</strong></p>
<div class="dxycode"><pre class="brush:bash;">powercfg /h on</pre></div>
<p>3. 禁用混合睡眠(仅台式机)</p>
<div class="dxycode"><pre class="brush:plain;">控制面板 → 电源选项 → 更改计划设置 → 更改高级电源设置 → 睡眠 → 允许混合睡眠 → 关闭
</pre></div>
<p><img alt="方案一:系统设置方式_图4" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04V51.png" /></p>
<p>4. 使用高性能电源计划</p>
<div class="dxycode"><pre class="brush:bash;"># 列出所有电源计划
powercfg /list
# 切换到高性能计划
powercfg /setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c</pre></div>
<p><strong>优点:</strong></p>
<p>操作简单,无需编程 系统级别的设置,对所有程序有效</p>
<p><strong>缺点:</strong></p>
<p>24小时不休眠,耗电量大 需要手动更改系统设置 可能忘记在不使用时恢复省电模式</p>
<p><img alt="方案一:系统设置方式_图5" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04R47.png" /></p>
<p class="maodian"></p><h4>方案二:程序级防休眠(推荐)</h4>
<p>通过调用 Windows API,让程序运行时<strong>临时阻止系统休眠</strong>,程序退出后自动恢复正常电源管理。</p>
<p>核心 API:SetThreadExecutionState</p>
<div class="dxycode"><pre class="brush:plain;">EXECUTION_STATE SetThreadExecutionState(
EXECUTION_STATE esFlags
);
</pre></div>
<p><strong>参数说明:</strong></p>
<table><tbody><tr><th style="text-align:center">标志</th><th style="text-align:center">值</th><th style="text-align:center">说明</th></tr><tr><td style="text-align:center">ES_CONTINUOUS</td><td style="text-align:center">0x80000000</td><td style="text-align:center">持续生效(直到清除或程序退出)</td></tr><tr><td style="text-align:center">ES_SYSTEM_REQUIRED</td><td style="text-align:center">0x00000001</td><td style="text-align:center">阻止系统自动睡眠</td></tr><tr><td style="text-align:center">ES_DISPLAY_REQUIRED</td><td style="text-align:center">0x00000002</td><td style="text-align:center">阻止显示器自动关闭</td></tr><tr><td style="text-align:center">ES_AWAYMODE_REQUIRED</td><td style="text-align:center">0x00000040</td><td style="text-align:center">启用离开模式(媒体播放器专用)</td></tr></tbody></table>
<p><strong>组合使用:</strong></p>
<div class="dxycode"><pre class="brush:plain;">// 阻止系统睡眠,允许显示器关闭
ES_CONTINUOUS | ES_SYSTEM_REQUIRED
// 阻止系统睡眠,同时保持显示器开启
ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED
// 恢复正常电源管理
ES_CONTINUOUS
</pre></div>
<p><strong>工作原理:</strong></p>
<p>程序调用 API 设置执行状态标志 Windows 电源管理器检测到标志后不会自动进入睡眠 <strong>用户手动触发的睡眠操作(如按电源键)仍然有效</strong> 程序退出时系统自动清除标志 如果程序崩溃,系统也会自动清除(安全机制)</p>
<p><strong>优点:</strong></p>
<ul><li>不影响系统设置,程序退出后自动恢复</li><li>支持 S0、S3 等所有睡眠模式</li><li>不需要管理员权限</li><li>用户仍可以手动控制电源</li></ul>
<p><strong>缺点:</strong></p>
<ul><li>需要编程实现</li><li>仅在程序运行时有效</li></ul>
<p class="maodian"></p><h3>代码实现</h3>
<p class="maodian"></p><h4>C# 版本</h4>
<p>基础版本(支持显示器控制)</p>
<div class="dxycode"><pre class="brush:csharp;">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>
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);
}
}
}</pre></div>
<p>使用示例</p>
<p><strong>WinForms 应用程序:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// 窗口加载时阻止休眠
this.Load += (s, e) => SleepPreventer.PreventSleep();
// 窗口关闭时恢复
this.FormClosing += (s, e) => SleepPreventer.AllowSleep();
}
}</pre></div>
<p><strong>WPF 应用程序:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">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);
}
}</pre></div>
<p><strong>控制台应用程序:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">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);
}
}
}</pre></div>
<p><strong>Windows 服务:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">public partial class MyService : ServiceBase
{
protected override void OnStart(string[] args)
{
// 服务启动时阻止休眠
SleepPreventer.PreventSleep();
// 启动业务逻辑
StartWorkThread();
}
protected override void OnStop()
{
// 服务停止时恢复
SleepPreventer.AllowSleep();
// 停止业务逻辑
StopWorkThread();
}
}</pre></div>
<p class="maodian"></p><h4>C++ 版本</h4>
<p>基础版本</p>
<div class="dxycode"><pre class="brush:csharp;">// 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</pre></div>
<div class="dxycode"><pre class="brush:csharp;">// 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);
}</pre></div>
<p>面向对象版本(RAII 自动管理)</p>
<div class="dxycode"><pre class="brush:csharp;">// 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</pre></div>
<div class="dxycode"><pre class="brush:csharp;">// 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);
}
}</pre></div>
<p>使用示例</p>
<p><strong>控制台应用程序:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">#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;
}</pre></div>
<p><strong>使用 RAII 版本:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">#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;
}</pre></div>
<p><strong>Qt 应用程序:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">// 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;
};</pre></div>
<div class="dxycode"><pre class="brush:csharp;">// 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);
}</pre></div>
<p><strong>MFC 应用程序:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">// 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();
}</pre></div>
<p class="maodian"></p><h3>常见问题解答</h3>
<p class="maodian"></p><h4>Q1: 为什么笔记本合盖后程序还能运行,但台式机睡眠后就不行?</h4>
<p><strong>A:</strong> 因为两者使用的睡眠技术不同:</p>
<p><strong>笔记本(S0 Modern Standby)</strong>:</p>
<ul><li>保持网络连接(Connected Standby)</li><li>向日葵等软件可以通过网络唤醒系统</li><li>类似手机的"息屏"状态</li></ul>
<p><strong>台式机(S3 传统睡眠)</strong>:</p>
<ul><li>网络适配器断电,连接断开</li><li>无法通过网络唤醒(除非配置 WOL)</li><li>所有用户程序暂停</li></ul>
<p><strong>解决方案:</strong></p>
<ul><li>台式机:使用本文提供的 SleepPreventer 类</li><li>或配置 Wake-on-LAN(需要主板和网卡支持)</li></ul>
<p class="maodian"></p><h4>Q2: SetThreadExecutionState 会影响用户手动睡眠操作吗?</h4>
<p><strong>A:</strong><strong>不会</strong>。此 API 只阻止系统<strong>自动</strong>进入睡眠,不影响用户主动操作:</p>
<ul><li>用户点击"开始菜单 → 睡眠"仍然有效</li><li>笔记本合盖仍会睡眠(根据电源设置)</li><li>按电源键的行为由 BIOS/系统设置决定</li><li>不会阻止用户手动触发的睡眠</li></ul>
<p>这是 Windows 设计的安全机制,确保用户始终有最高控制权。</p>
<p class="maodian"></p><h4>Q3: 程序崩溃或被强制结束,系统会一直不睡眠吗?</h4>
<p><strong>A:</strong><strong>不会</strong>。Windows 有安全机制:</p>
<ul><li>程序进程终止时,系统自动清除所有执行状态标志</li><li>即使程序崩溃、被杀进程、蓝屏,系统都会恢复正常</li><li>不需要担心"忘记调用 AllowSleep"会导致系统永久不睡眠</li></ul>
<p><strong>建议:</strong></p>
<ul><li>仍应在程序退出时主动调用 AllowSleep()</li><li>这是良好的编程习惯,体现对系统资源的尊重</li></ul>
<p>主动调用 AllowSleep() 这是良好的编程习惯,体现对系统资源的尊重</p>
<p class="maodian"></p><h4>Q4: 为什么有时候设置了还是会睡眠?</h4>
<p><strong>可能的原因:</strong></p>
<p><strong>API 调用失败</strong></p>
<div class="dxycode"><pre class="brush:csharp;">// 检查返回值
uint result = SetThreadExecutionState(...);
if (result == 0)
{
// 失败,获取错误码
int error = Marshal.GetLastWin32Error();
}</pre></div>
<p><strong>标志设置不正确</strong></p>
<ul><li>必须包含 ES_CONTINUOUS</li><li>必须包含 ES_SYSTEM_REQUIRED 或 ES_DISPLAY_REQUIRED</li></ul>
<p><strong>被其他程序或策略覆盖</strong></p>
<ul><li>组策略禁用了应用程序阻止睡眠</li><li>其他程序调用了相同的 API</li></ul>
<p><strong>电源按钮被按下</strong></p>
<ul><li>用户主动操作优先级最高</li></ul>
<p><strong>调试方法:</strong></p>
<div class="dxycode"><pre class="brush:plain;"># 查看哪些程序正在阻止睡眠
powercfg /requests
</pre></div>
<p>输出示例:</p>
<div class="dxycode"><pre class="brush:plain;">DISPLAY:
\Device\HarddiskVolume3\Program Files\MyApp\MyApp.exe
SYSTEM:
\Device\HarddiskVolume3\Program Files\MyApp\MyApp.exe
</pre></div>
<p><img alt="Q4: 为什么有时候设置了还是会睡眠?" src="https://zhuji.jb51.net/uploads/allimg/20260108/2-26010QF04T56.png" /></p>
<p class="maodian"></p><h4>Q5: 是否需要管理员权限?</h4>
<p><strong>A:</strong><strong>不需要</strong>。SetThreadExecutionState 是用户级 API:</p>
<ul><li>普通用户权限即可调用</li><li>不需要提升权限(UAC)</li><li>可以在任何应用程序类型中使用</li></ul>
<p>但是<strong>修改系统电源设置</strong>需要管理员权限:</p>
<div class="dxycode"><pre class="brush:plain;"># 需要管理员权限
powercfg /h off
powercfg /change standby-timeout-ac 0
</pre></div>
<p class="maodian"></p><h4>Q6: 对笔记本电池有影响吗?</h4>
<p><strong>A:</strong> 有一定影响,取决于使用方式:</p>
<table><tbody><tr><th>场景</th><th>影响</th><th>建议</th></tr><tr><td><strong>接通电源</strong></td><td>无影响</td><td>正常使用</td></tr><tr><td><strong>使用电池</strong></td><td>电池消耗加快</td><td>谨慎使用,建议接通电源</td></tr><tr><td><strong>仅阻止系统睡眠</strong></td><td>影响较小</td><td>可接受</td></tr><tr><td><strong>同时保持显示器开启</strong></td><td>影响较大</td><td>尽量避免</td></tr></tbody></table>
<p><strong>节能建议:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">// 检测电源状态
if (SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online)
{
// 接通电源,阻止睡眠
SleepPreventer.PreventSleep();
}
else
{
// 使用电池,允许睡眠以节能
SleepPreventer.AllowSleep();
}</pre></div>
<p class="maodian"></p><h4>Q7: 支持哪些 Windows 版本?</h4>
<p><strong>A:</strong>SetThreadExecutionState API 支持:</p>
<ul><li>Windows XP SP1 及以上</li><li>Windows Vista/7/8/8.1/10/11</li><li>Windows Server 2003 及以上</li></ul>
<p><strong>兼容性非常好</strong>,几乎所有现代 Windows 系统都支持。</p>
<p class="maodian"></p><h4>Q8: 如何在多线程环境中使用?</h4>
<p><strong>A:</strong>SetThreadExecutionState 是线程局部的,但标志是全局共享的:</p>
<div class="dxycode"><pre class="brush:csharp;">// 错误示例:多个线程同时设置可能冲突
Thread thread1 = new Thread(() => {
SleepPreventer.PreventSleep();
DoWork1();
SleepPreventer.AllowSleep(); // ⚠️ 会影响其他线程
});
Thread thread2 = new Thread(() => {
SleepPreventer.PreventSleep();
DoWork2();
// thread1 调用 AllowSleep 后,这里的设置会被清除
});</pre></div>
<p><strong>推荐方案:</strong></p>
<div class="dxycode"><pre class="brush:csharp;">// 在主线程统一管理
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);
}
}
}
}</pre></div>
<p class="maodian"></p><h4>Q9: 与其他电源管理工具冲突吗?</h4>
<p><strong>A:</strong> 一般不会,但有特殊情况:</p>
<p><strong>兼容的工具:</strong></p>
<ul><li>Caffeine</li><li>Don’t Sleep</li><li>PowerToys (Awake 模块)</li><li>游戏模式</li><li>Windows 焦点辅助</li></ul>
<p><strong>可能冲突的情况:</strong></p>
<ul><li>组策略强制睡眠设置</li><li>企业设备管理策略</li><li>BIOS 级别的电源管理</li></ul>
<p><strong>检查方法:</strong></p>
<div class="dxycode"><pre class="brush:bash;"># 查看活动的电源请求
powercfg /requests
# 查看组策略设置
gpedit.msc → 计算机配置 → 管理模板 → 系统 → 电源管理</pre></div>
<p class="maodian"></p><h4>Q10: 远程桌面断开后,程序会睡眠吗?</h4>
<p><strong>A:</strong> 取决于系统配置:</p>
<p><strong>Windows 10/11 默认行为:</strong></p>
<ul><li>远程桌面断开后,<strong>服务器不会自动睡眠</strong></li><li>但会关闭显示器(除非设置了 ES_DISPLAY_REQUIRED)</li></ul>
<p><strong>如果需要保持远程可用:</strong></p>
<div class="dxycode"><pre class="brush:plain;">// 保持显示器开启,确保远程桌面可用
SleepPreventer.PreventSleep(SleepPreventer.PreventMode.SystemAndDisplay);
</pre></div>
<p><strong>组策略设置:</strong></p>
<div class="dxycode"><pre class="brush:plain;">gpedit.msc → 计算机配置 → 管理模板 → Windows 组件 → 远程桌面服务
→ 远程桌面会话主机 → 连接 → "允许用户通过使用远程桌面服务远程连接" → 已启用
</pre></div>
<p class="maodian"></p><h3>总结</h3>
<p class="maodian"></p><h4>关键要点</h4>
<p><strong>理解不同的睡眠模式</strong></p>
<ul><li>S0 Modern Standby(笔记本):保持网络,部分程序可运行</li><li>S3 传统睡眠(台式机):暂停所有程序,断开网络</li><li>S4 休眠:完全断电,所有程序停止</li></ul>
<p><strong>选择合适的解决方案</strong></p>
<ul><li><strong>临时测试</strong>:系统设置禁用睡眠</li><li><strong>生产环境</strong>:程序级防休眠(推荐)</li><li><strong>服务器</strong>:完全禁用休眠功能</li></ul>
<p><strong>程序级防休眠优势</strong></p>
<ul><li>不影响系统设置</li><li>程序退出自动恢复</li><li>用户仍可手动控制</li><li>无需管理员权限</li></ul>
<p><strong>最佳实践</strong></p>
<ul><li>在程序启动时调用 PreventSleep()</li><li>在程序退出时调用 AllowSleep()</li><li>根据场景选择是否保持显示器开启</li><li>考虑笔记本电池使用情况</li></ul>
<p class="maodian"></p><h4>代码使用建议</h4>
<table><tbody><tr><th style="text-align:center">应用类型</th><th style="text-align:center">推荐模式</th><th style="text-align:center">说明</th></tr><tr><td style="text-align:center">后台服务</td><td style="text-align:center">SystemOnly</td><td style="text-align:center">允许显示器关闭以节能</td></tr><tr><td style="text-align:center">监控界面</td><td style="text-align:center">SystemAndDisplay</td><td style="text-align:center">保持屏幕显示</td></tr><tr><td style="text-align:center">数据采集</td><td style="text-align:center">SystemOnly</td><td style="text-align:center">无界面程序</td></tr><tr><td style="text-align:center">远程控制</td><td style="text-align:center">SystemAndDisplay</td><td style="text-align:center">确保远程可用</td></tr><tr><td style="text-align:center">工业控制</td><td style="text-align:center">SystemOnly</td><td style="text-align:center">保持 PLC 通信</td></tr></tbody></table>
<p>以上就是Windows系统进入了休眠或睡眠状态怎么办?如何解决的详细内容,更多相关资料请阅读琼殿技术社区其它文章!</p>
頁:
[1]