最近寫了一個下載程序,發現有一個問題:掛機下載的時候,下載任務會因為系統休眠被終止掉。
最開始我的解決方法是關閉休眠,后來發現這種策略並不是很好:下載完成后,如果仍然繼續保持開機狀態浪費電。
因此,最好的方式是:在下載的時候阻止系統休眠。即不會因為休眠而終止下載任務,下載完成后自動轉為休眠狀態省電,都不用做下載完成后自動關機功能了。
查了一下相關文章,可以通過這個SetThreadExecutionState API實現阻止系統休眠。它在C#中的聲明方式如下:
[DllImport("kernel32.dll")]
static extern uint SetThreadExecutionState(ExecutionFlag flags);
[Flags]
enum ExecutionFlag : uint
{
System = 0x00000001,
Display = 0x00000002,
Continuous = 0x80000000,
}
它就一個flags參數,這個參數有三個選項,可以組合使用。主要說明如下:
-
只使用Continuous參數時,則是恢復系統休眠策略。
-
不使用Continuous參數時,實現阻止系統休眠或顯示器關閉一次
-
組合使用Continuous參數時,實現阻止系統休眠或顯示器關閉至線程終止
因此,它一共有三種使用方式,這里我就封裝了一下:
class SystemSleepManagement
{
//定義API函數
[DllImport("kernel32.dll")]
static extern uint SetThreadExecutionState(ExecutionFlag flags);
[Flags]
enum ExecutionFlag : uint
{
System = 0x00000001,
Display = 0x00000002,
Continuous = 0x80000000,
}
/// <summary>
///阻止系統休眠,直到線程結束恢復休眠策略
/// </summary>
/// <param name="includeDisplay">是否阻止關閉顯示器</param>
public static void PreventSleep(bool includeDisplay = false)
{
if (includeDisplay)
SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Display | ExecutionFlag.Continuous);
else
SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Continuous);
}
/// <summary>
///恢復系統休眠策略
/// </summary>
public static void RestoreSleep()
{
SetThreadExecutionState(ExecutionFlag.Continuous);
}
/// <summary>
///重置系統休眠計時器
/// </summary>
/// <param name="includeDisplay">是否阻止關閉顯示器</param>
public static void ResetSleepTimer(bool includeDisplay = false)
{
if (includeDisplay)
SetThreadExecutionState(ExecutionFlag.System | ExecutionFlag.Display);
else
SetThreadExecutionState(ExecutionFlag.System);
}
}
因此,要實現下載時阻止程序休眠,則有兩種實現方式:
-
下載期間起計時器定期執行ResetSleepTimer函數
-
下載開始時執行PreventSleep函數,下載結束后執行RestoreSleep函數。
另外,和阻止系統休眠類似,有的程序還需要有阻止屏保功能。因為我的程序目前還用不到,這里就不多講了。需要此功能的朋友可以參看下面兩篇文章。