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);
else
setthreadexecutionstate(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);
else
setthreadexecutionstate(executionflag.system);
}
catch { }
}
}
使用实例
void time()
{
preventsleep(true);
}
到此这篇关于c#中阻止硬件休眠的多种实现方法的文章就介绍到这了,更多相关c# 阻止硬件休眠内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论