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í)器(推薦用于長(zhǎng)時(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:長(zhǎng)時(shí)間操作期間阻止休眠(如文件傳輸)
// 開始長(zhǎng)時(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()) { // 長(zhǎng)時(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-04C# 多線程編程技術(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-06UGUI實(shí)現(xiàn)隨意調(diào)整Text中的字體間距
這篇文章主要為大家詳細(xì)介紹了UGUI實(shí)現(xiàn)隨意調(diào)整字體間距的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03