如何阻止Windows 11进入睡眠?SetThreadExecutionState尝试无效
阻止Windows 11进入睡眠状态的解决方案
问题重现
尝试通过SetThreadExecutionState的多种参数组合阻止Windows 11睡眠,代码示例如下:
private const uint ES_CONTINUOUS = 0x80000000; private const uint ES_SYSTEM_REQUIRED = 0x00000001; private const uint ES_DISPLAY_REQUIRED = 0x00000002; private const uint ES_AWAYMODE_REQUIRED = 0x00000040; // 尝试过的调用组合 // ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED for (;;) { SetThreadExecutionState(ES_SYSTEM_REQUIRED); // SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_CONTINUOUS); // SetThreadExecutionState(ES_AWAYMODE_REQUIRED) // SetThreadExecutionState(ES_AWAYMODE_REQUIRED | ES_CONTINUOUS); // SetThreadExecutionState(ES_AWAYMODE_REQUIRED | ES_SYSTEM_REQUIRED | ES_CONTINUOUS); Thread.Sleep(10000); Console.WriteLine("The current time is: " + DateTime.Now); }
无论在循环内/外调用该函数,系统仍会在3-5分钟后进入睡眠状态。
可能的原因
ES_CONTINUOUS参数使用不当:单独调用ES_SYSTEM_REQUIRED仅会临时阻止睡眠,系统超时后会恢复原有策略;ES_CONTINUOUS需与其他参数组合使用,才能让唤醒请求持续生效。- Windows 11现代待机(Modern Standby)机制:如果设备启用了S0低功耗待机模式,传统的
SetThreadExecutionState可能无法完全覆盖系统的睡眠触发逻辑。 - 系统电源策略限制:组策略、管理员设置或厂商电源管理软件可能强制系统进入睡眠,忽略应用层的唤醒请求。
- 程序电池优化设置:Windows的电池优化功能可能限制了程序的后台活动,导致唤醒请求被系统忽略。
解决方案
1. 修正SetThreadExecutionState的用法
正确的调用方式是:
- 程序启动时,调用一次
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED),标记持续的系统唤醒请求; - 每隔一段时间(推荐1-2分钟)调用一次
SetThreadExecutionState(ES_SYSTEM_REQUIRED),刷新唤醒请求,避免系统超时重置。
修正后的代码示例:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern uint SetThreadExecutionState(uint esFlags); private const uint ES_CONTINUOUS = 0x80000000; private const uint ES_SYSTEM_REQUIRED = 0x00000001; static void Main(string[] args) { // 初始化持续唤醒请求 SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED); try { while (true) { // 刷新唤醒请求 SetThreadExecutionState(ES_SYSTEM_REQUIRED); Console.WriteLine("当前时间: " + DateTime.Now); Thread.Sleep(60000); // 每分钟刷新一次 } } finally { // 程序退出时清除唤醒请求 SetThreadExecutionState(ES_CONTINUOUS); } }
2. 使用Power API应对现代待机(Modern Standby)
如果设备启用了S0待机模式,需使用PowerSetRequest API来创建系统唤醒请求,示例代码如下:
using System; using System.Runtime.InteropServices; using System.Threading; class Program { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct POWER_REQUEST_CONTEXT { public UInt32 Version; public UInt32 Flags; [MarshalAs(UnmanagedType.LPWStr)] public string SimpleReasonString; } [DllImport("kernel32.dll")] private static extern IntPtr PowerCreateRequest(ref POWER_REQUEST_CONTEXT Context); [DllImport("kernel32.dll")] private static extern bool PowerSetRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType); [DllImport("kernel32.dll")] private static extern bool PowerClearRequest(IntPtr PowerRequestHandle, PowerRequestType RequestType); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hObject); private enum PowerRequestType { PowerRequestDisplayRequired = 0, PowerRequestSystemRequired, PowerRequestAwayModeRequired, PowerRequestMaximum } static void Main(string[] args) { // 创建电源请求上下文 POWER_REQUEST_CONTEXT powerRequestContext = new POWER_REQUEST_CONTEXT(); powerRequestContext.Version = 0; powerRequestContext.Flags = 0; powerRequestContext.SimpleReasonString = "阻止系统睡眠"; // 创建电源请求句柄 IntPtr powerRequestHandle = PowerCreateRequest(ref powerRequestContext); if (powerRequestHandle != IntPtr.Zero) { // 设置系统唤醒请求 PowerSetRequest(powerRequestHandle, PowerRequestType.PowerRequestSystemRequired); try { while (true) { Console.WriteLine("当前时间: " + DateTime.Now); Thread.Sleep(60000); } } finally { // 清除请求并释放句柄 PowerClearRequest(powerRequestHandle, PowerRequestType.PowerRequestSystemRequired); CloseHandle(powerRequestHandle); } } else { Console.WriteLine("创建电源请求失败"); } } }
3. 检查系统设置
- 电池优化设置:打开「设置」→「系统」→「电池」→「电池优化」,找到你的程序,设置为「不允许」,确保程序后台活动不受限制。
- 电源计划设置:检查当前电源计划的「睡眠」超时设置,确保没有被强制设置为短时间;若使用笔记本,检查厂商电源管理软件是否有额外的睡眠策略。
- 组策略检查:运行
gpedit.msc,查看「计算机配置」→「管理模板」→「系统」→「电源管理」下的策略,确认没有强制睡眠的设置。
内容的提问来源于stack exchange,提问作者Rowan Smith
相关产品推荐
相关产品推荐

