C#中阻止硬件休眠的多種實(shí)現(xiàn)方法
C#中如何阻止硬件休眠
在 C# 中阻止系統(tǒng)進(jìn)入休眠狀態(tài)(包括顯示關(guān)閉和系統(tǒng)休眠)需要使用 Windows API。以下是完整的實(shí)現(xiàn)方案,包含多種控制級(jí)別和實(shí)際應(yīng)用場(chǎng)景:
核心解決方案:使用 SetThreadExecutionState API
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class SleepPreventer : IDisposable
{
// 導(dǎo)入 Windows API
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern uint SetThreadExecutionState(uint esFlags);
// 執(zhí)行狀態(tài)標(biāo)志
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>
/// 初始化并阻止系統(tǒng)休眠
/// </summary>
/// <param name="preventDisplaySleep">是否阻止顯示器關(guān)閉</param>
/// <param name="preventSystemSleep">是否阻止系統(tǒng)休眠</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;
}
// 設(shè)置新狀態(tài)并保存之前的狀態(tài)
_previousState = SetThreadExecutionState(newState);
if (_previousState == 0)
{
throw new Exception("設(shè)置執(zhí)行狀態(tài)失敗: " + Marshal.GetLastWin32Error());
}
}
/// <summary>
/// 恢復(fù)原始狀態(tài)(允許系統(tǒng)休眠)
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
// 恢復(fù)之前的執(zhí)行狀態(tài)
if (_previousState != 0)
{
SetThreadExecutionState(_previousState);
}
_isDisposed = true;
}
}
~SleepPreventer()
{
Dispose(false);
}
/// <summary>
/// 臨時(shí)重置休眠計(jì)時(shí)器(推薦用于長時(shí)間操作)
/// </summary>
public static void ResetSleepTimer(bool resetDisplay = true)
{
uint flags = ES_SYSTEM_REQUIRED;
if (resetDisplay) flags |= ES_DISPLAY_REQUIRED;
SetThreadExecutionState(flags);
}
}
使用示例
場(chǎng)景 1:長時(shí)間操作期間阻止休眠(如文件傳輸)
// 開始長時(shí)間操作
using (var sleepLock = new SleepPreventer())
{
// 執(zhí)行耗時(shí)操作(如大文件傳輸)
TransferLargeFile("source.zip", "destination.zip");
// 在循環(huán)中定期重置計(jì)時(shí)器
for (int i = 0; i < 100; i++)
{
DoWorkChunk(i);
SleepPreventer.ResetSleepTimer(); // 每部分完成時(shí)重置計(jì)時(shí)器
}
} // 離開 using 范圍后自動(dòng)允許休眠
場(chǎng)景 2:媒體播放期間保持喚醒
public class MediaPlayer : IDisposable
{
private SleepPreventer _sleepPreventer;
public void Play()
{
// 播放開始時(shí)阻止休眠
_sleepPreventer = new SleepPreventer(preventDisplaySleep: true);
// 開始播放...
}
public void Pause()
{
// 暫停時(shí)允許休眠
_sleepPreventer?.Dispose();
_sleepPreventer = null;
}
public void Dispose()
{
_sleepPreventer?.Dispose();
}
}
場(chǎng)景 3:后臺(tái)服務(wù)保持系統(tǒng)喚醒
public class BackgroundService
{
private SleepPreventer _sleepPreventer;
public void StartMonitoring()
{
// 阻止系統(tǒng)休眠但允許顯示器關(guān)閉
_sleepPreventer = new SleepPreventer(preventDisplaySleep: false,
preventSystemSleep: true);
// 開始監(jiān)控...
}
public void Stop()
{
_sleepPreventer?.Dispose();
}
}
高級(jí)控制:使用 Windows 電源請(qǐng)求
對(duì)于更復(fù)雜的場(chǎng)景(需要系統(tǒng)完全保持喚醒狀態(tài)),可以使用 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);
}
實(shí)際應(yīng)用技巧
最小化影響:
// 僅在必要時(shí)阻止休眠
if (operationWillTakeMoreThan(TimeSpan.FromMinutes(10)))
{
using (var preventer = new SleepPreventer())
{
ExecuteLongOperation();
}
}
用戶配置選項(xiàng):
// 在設(shè)置中添加選項(xiàng)
if (Settings.PreventSleepDuringOperations)
{
SleepPreventer.ResetSleepTimer();
}
處理系統(tǒng)電源事件:
Microsoft.Win32.SystemEvents.PowerModeChanged += (s, e) =>
{
if (e.Mode == PowerModes.Suspend)
{
// 系統(tǒng)即將休眠,保存狀態(tài)
SaveCurrentState();
}
};
多顯示器場(chǎng)景:
// 檢測(cè)是否有外接顯示器
bool hasExternalDisplay = Screen.AllScreens.Length > 1;
// 僅在無外接顯示器時(shí)阻止顯示器關(guān)閉
using (var preventer = new SleepPreventer(
preventDisplaySleep: !hasExternalDisplay))
{
// 執(zhí)行操作...
}


超時(shí)處理
// 設(shè)置最大阻止時(shí)間
using (var timeout = new System.Threading.Timer(_ =>
{
preventer?.Dispose();
}, null, TimeSpan.FromHours(2), Timeout.InfiniteTimeSpan))
{
using (var preventer = new SleepPreventer())
{
// 長時(shí)間操作...
}
}
其他使用
public class SystemSleepAPI
{
//定義API函數(shù)
[DllImport("kernel32.dll")]
static extern uint SetThreadExecutionState(ExecutionFlag flags);
[Flags]
enum ExecutionFlag : uint
{
System = 0x00000001,
Display = 0x00000002,
Continus = 0x80000000,
}
/// <summary>
///阻止系統(tǒng)休眠,直到線程結(jié)束恢復(fù)休眠策略
/// </summary>
/// <param name="includeDisplay">是否阻止關(guān)閉顯示器</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>
///恢復(fù)系統(tǒng)休眠策略
/// </summary>
public static void ResotreSleep()
{
try { SetThreadExecutionState(ExecutionFlag.Continus); } catch { }
}
/// <summary>
///重置系統(tǒng)休眠計(jì)時(shí)器
/// </summary>
/// <param name="includeDisplay">是否阻止關(guān)閉顯示器</param>
public static void ResetSleepTimer(bool includeDisplay = false)
{
try
{
if (includeDisplay)
SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Display);
else
SetThreadExecutionState(ExecutionFlag.System);
}
catch { }
}
}
使用實(shí)例
void time()
{
PreventSleep(true);
}
到此這篇關(guān)于C#中阻止硬件休眠的多種實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)C# 阻止硬件休眠內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)讓ListBox適應(yīng)最大Item寬度的方法
這篇文章主要介紹了C#實(shí)現(xiàn)讓ListBox適應(yīng)最大Item寬度的方法,涉及ListBox控件的操作技巧,需要的朋友可以參考下2015-05-05
詳解WPF如何顯示具有層級(jí)關(guān)系的數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了在WPF中如何顯示具有層級(jí)關(guān)系的數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
C# 多線程編程技術(shù)基礎(chǔ)知識(shí)入門
這篇文章主要介紹了C# 多線程編程技術(shù)基礎(chǔ)知識(shí),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2020-02-02
基于mvc5+ef6+Bootstrap框架實(shí)現(xiàn)身份驗(yàn)證和權(quán)限管理
最近剛做完一個(gè)項(xiàng)目,項(xiàng)目架構(gòu)師使用mvc5+ef6+Bootstrap,用的是vs2015,數(shù)據(jù)庫是sql server2014。下面小編把mvc5+ef6+Bootstrap項(xiàng)目心得之身份驗(yàn)證和權(quán)限管理模塊的實(shí)現(xiàn)思路分享給大家,需要的朋友可以參考下2016-06-06
UGUI實(shí)現(xiàn)隨意調(diào)整Text中的字體間距
這篇文章主要為大家詳細(xì)介紹了UGUI實(shí)現(xiàn)隨意調(diào)整字體間距的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03

