当前位置: 首页 > news >正文

C#中如何阻止硬件休眠

C#中如何阻止硬件休眠

在 C# 中阻止系统进入休眠状态(包括显示关闭和系统休眠)需要使用 Windows API。以下是完整的实现方案,包含多种控制级别和实际应用场景:

核心解决方案:使用 SetThreadExecutionState API

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;public class SleepPreventer : IDisposable
{// 导入 Windows API[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;private const uint ES_DISPLAY_REQUIRED = 0x00000002;private const uint ES_AWAYMODE_REQUIRED = 0x00000040;private uint _previousState;private bool _isDisposed;/// <summary>/// 初始化并阻止系统休眠/// </summary>/// <param name="preventDisplaySleep">是否阻止显示器关闭</param>/// <param name="preventSystemSleep">是否阻止系统休眠</param>public SleepPreventer(bool preventDisplaySleep = true, bool preventSystemSleep = true){uint newState = ES_CONTINUOUS;if (preventSystemSleep){newState |= ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED;}if (preventDisplaySleep){newState |= ES_DISPLAY_REQUIRED;}// 设置新状态并保存之前的状态_previousState = SetThreadExecutionState(newState);if (_previousState == 0){throw new Exception("设置执行状态失败: " + Marshal.GetLastWin32Error());}}/// <summary>/// 恢复原始状态(允许系统休眠)/// </summary>public void Dispose(){Dispose(true);GC.SuppressFinalize(this);}protected virtual void Dispose(bool disposing){if (!_isDisposed){// 恢复之前的执行状态if (_previousState != 0){SetThreadExecutionState(_previousState);}_isDisposed = true;}}~SleepPreventer(){Dispose(false);}/// <summary>/// 临时重置休眠计时器(推荐用于长时间操作)/// </summary>public static void ResetSleepTimer(bool resetDisplay = true){uint flags = ES_SYSTEM_REQUIRED;if (resetDisplay) flags |= ES_DISPLAY_REQUIRED;SetThreadExecutionState(flags);}
}

使用示例

场景 1:长时间操作期间阻止休眠(如文件传输)

// 开始长时间操作
using (var sleepLock = new SleepPreventer())
{// 执行耗时操作(如大文件传输)TransferLargeFile("source.zip", "destination.zip");// 在循环中定期重置计时器for (int i = 0; i < 100; i++){DoWorkChunk(i);SleepPreventer.ResetSleepTimer(); // 每部分完成时重置计时器}
} // 离开 using 范围后自动允许休眠

场景 2:媒体播放期间保持唤醒

public class MediaPlayer : IDisposable
{private SleepPreventer _sleepPreventer;public void Play(){// 播放开始时阻止休眠_sleepPreventer = new SleepPreventer(preventDisplaySleep: true);// 开始播放...}public void Pause(){// 暂停时允许休眠_sleepPreventer?.Dispose();_sleepPreventer = null;}public void Dispose(){_sleepPreventer?.Dispose();}
}

场景 3:后台服务保持系统唤醒

public class BackgroundService
{private SleepPreventer _sleepPreventer;public void StartMonitoring(){// 阻止系统休眠但允许显示器关闭_sleepPreventer = new SleepPreventer(preventDisplaySleep: false, preventSystemSleep: true);// 开始监控...}public void Stop(){_sleepPreventer?.Dispose();}
}

高级控制:使用 Windows 电源请求
对于更复杂的场景(需要系统完全保持唤醒状态),可以使用 PowerCreateRequest API:

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr PowerCreateRequest(ref POWER_REQUEST_CONTEXT context);[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool PowerSetRequest(IntPtr powerRequest, POWER_REQUEST_TYPE requestType);[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool PowerClearRequest(IntPtr powerRequest, POWER_REQUEST_TYPE requestType);[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct POWER_REQUEST_CONTEXT
{public uint Version;public uint Flags;[MarshalAs(UnmanagedType.LPWStr)]public string SimpleReasonString;
}private enum POWER_REQUEST_TYPE
{PowerRequestDisplayRequired,PowerRequestSystemRequired,PowerRequestAwayModeRequired
}public class PowerRequest : IDisposable
{private IntPtr _handle;private bool _isDisposed;public PowerRequest(string reason){var context = new POWER_REQUEST_CONTEXT{Version = 0,Flags = 0,SimpleReasonString = reason};_handle = PowerCreateRequest(ref context);if (_handle == IntPtr.Zero)throw new Win32Exception(Marshal.GetLastWin32Error());if (!PowerSetRequest(_handle, POWER_REQUEST_TYPE.PowerRequestSystemRequired))throw new Win32Exception(Marshal.GetLastWin32Error());}public void Dispose(){if (!_isDisposed){if (_handle != IntPtr.Zero){PowerClearRequest(_handle, POWER_REQUEST_TYPE.PowerRequestSystemRequired);CloseHandle(_handle);_handle = IntPtr.Zero;}_isDisposed = true;}}[DllImport("kernel32.dll", SetLastError = true)]private static extern bool CloseHandle(IntPtr hObject);
}

实际应用技巧

最小化影响:

// 仅在必要时阻止休眠
if (operationWillTakeMoreThan(TimeSpan.FromMinutes(10)))
{using (var preventer = new SleepPreventer()){ExecuteLongOperation();}
}

用户配置选项:

// 在设置中添加选项
if (Settings.PreventSleepDuringOperations)
{SleepPreventer.ResetSleepTimer();
}

处理系统电源事件:

Microsoft.Win32.SystemEvents.PowerModeChanged += (s, e) => 
{if (e.Mode == PowerModes.Suspend){// 系统即将休眠,保存状态SaveCurrentState();}
};

多显示器场景:

// 检测是否有外接显示器
bool hasExternalDisplay = Screen.AllScreens.Length > 1;// 仅在无外接显示器时阻止显示器关闭
using (var preventer = new SleepPreventer(preventDisplaySleep: !hasExternalDisplay))
{// 执行操作...
}

在这里插入图片描述
在这里插入图片描述
超时处理

// 设置最大阻止时间
using (var timeout = new System.Threading.Timer(_ => 
{preventer?.Dispose();
}, null, TimeSpan.FromHours(2), Timeout.InfiniteTimeSpan))
{using (var preventer = new SleepPreventer()){// 长时间操作...}
}

其他使用

public class SystemSleepAPI
{//定义API函数[DllImport("kernel32.dll")]static extern uint SetThreadExecutionState(ExecutionFlag flags);[Flags]enum ExecutionFlag : uint{System = 0x00000001,Display = 0x00000002,Continus = 0x80000000,}/// <summary>///阻止系统休眠,直到线程结束恢复休眠策略/// </summary>/// <param name="includeDisplay">是否阻止关闭显示器</param>public static void PreventSleep(bool includeDisplay = false){try{if (includeDisplay)SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Display | ExecutionFlag.Continus);elseSetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Continus);}catch { }}/// <summary>///恢复系统休眠策略/// </summary>public static void ResotreSleep(){try { SetThreadExecutionState(ExecutionFlag.Continus); } catch { }}/// <summary>///重置系统休眠计时器/// </summary>/// <param name="includeDisplay">是否阻止关闭显示器</param>public static void ResetSleepTimer(bool includeDisplay = false){try{if (includeDisplay)SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Display);elseSetThreadExecutionState(ExecutionFlag.System);}catch { }}
}

使用实例

void time()
{PreventSleep(true);
}
http://www.dtcms.com/a/278304.html

相关文章:

  • Vue 低代码可视化表单设计器 FcDesigner v3.3 版本发布!表格布局升级+精细化权限控制
  • JDK1.8 ReentrantLock相关源码
  • 代数基本定理
  • 多模态数据处理新趋势:阿里云ODPS技术栈深度解析与未来展望
  • RabbitMQ中队列长度限制(Queue Length Limit)详解
  • LVS的集群技术和分布式
  • hive的相关的优化
  • 传统机器学习在信用卡交易预测中的卓越表现:从R²=-0.0075到1.0000的华丽转身
  • Android 性能优化:启动优化全解析
  • Android 16系统源码_窗口动画(一)窗口过渡动画层级图分析
  • USB读写自动化压力测试
  • Android编译系统——基础介绍(一)
  • 微软发布BioEmu模型
  • spring shell 基础使用
  • PyTorch生成式人工智能(17)——变分自编码器详解与实现
  • 大话数据结构之 <链表>(C语言)
  • 8.服务通信:Feign深度优化 - 解密声明式调用与现代负载均衡内核
  • UV vs Pip:Python 包管理的革命性进化
  • 017 进程控制 —— 终止进程
  • CentOS 7服务器上使用Docker部署Notesnook的详细指导说明
  • Python爬虫打怪升级:数据获取疑难全解析
  • 天地图前端实现geoJson与wkt格式互转
  • C++面试5题--4day
  • Java陷阱之assert关键字详解
  • 使用layui的前端框架过程中,无法加载css和js怎么办?
  • 谷歌开源库gtest 框架安装与使用
  • CentOS系统哪些版本?分别适用于那些业务或网站类型?
  • 2025年Java后端社招面试:高频场景题+八股文面试题解析
  • toString
  • S7-1200 中 AT 覆盖参数的应用:灵活访问数据区域的实用指南