从 Windows 服务调用时,SetThreadExecutionState 不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5870280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SetThreadExecutionState is not working when called from windows service
提问by Prasad
I want prevent system from going to sleep/hibernate from a windows service.
I am calling SetThreadExecutionState
function to do that.
But it seems to have no effect.
I just want to know whether the function SetThreadExecutionState
will for windows services. If not what will be the alternative ways to that.
我想防止系统从 Windows 服务进入睡眠/休眠状态。我正在调用SetThreadExecutionState
函数来做到这一点。但是好像没什么效果。我只想知道该功能SetThreadExecutionState
是否适用于 Windows 服务。如果不是,那将是什么替代方法。
Below is the C# code i am using. I am calling it on Onstart
method of service.
下面是我正在使用的 C# 代码。我在Onstart
服务方法上调用它。
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint SetThreadExecutionState(EXECUTION_STATE esFlags);
private void KeepAlive()
{
SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS)
}
采纳答案by Roman Starkov
Calling SetThreadExecutionState without ES_CONTINUOUS simply resets the idle timer; to keep the display or system in the working state, the thread must call SetThreadExecutionState periodically.
在没有 ES_CONTINUOUS 的情况下调用 SetThreadExecutionState 只会重置空闲计时器;为了使显示器或系统保持在工作状态,线程必须定期调用 SetThreadExecutionState。
(source)
(来源)
You need to call this function every now and then. It's not a fire-and-forget.
您需要不时调用此函数。这不是一劳永逸。
回答by hebinda
SetThreadExecutionState is only valid for the thread that calls it. If it's called in a worker thread, even with ES_CONTINUOUS, once the worker thread is dead, the setting is not valid anymore and then screen saver will be on again.
SetThreadExecutionState 只对调用它的线程有效。如果在工作线程中调用它,即使使用 ES_CONTINUOUS,一旦工作线程死亡,设置将不再有效,然后屏幕保护程序将再次打开。
Calling this API from a Timer will wake up a worker thread before previous thread is dead and therefore makes it work.
从 Timer 调用此 API 将在前一个线程死之前唤醒一个工作线程,从而使其工作。
So if you call SetThreadExecutionState in your main thread, like UI thread in client applications, you don't need timer.
因此,如果您在主线程中调用 SetThreadExecutionState,就像客户端应用程序中的 UI 线程一样,则不需要计时器。
回答by PatrickV
Here's my solution, hope it helps. Seems to work on Windows 10. Usage:
这是我的解决方案,希望它有所帮助。似乎适用于 Windows 10。用法:
PowerUtilities.PreventPowerSave();
PowerUtilities.PreventPowerSave();
... then later
……后来
PowerUtilities.Shutdown();
PowerUtilities.Shutdown();
Not meant to be re-callable.
并不意味着可以重新调用。
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
namespace KeepAlive
{
public static class PowerUtilities
{
[Flags]
public enum EXECUTION_STATE : uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
// Legacy flag, should not be used.
// ES_USER_PRESENT = 0x00000004
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint SetThreadExecutionState(EXECUTION_STATE esFlags);
private static AutoResetEvent _event = new AutoResetEvent(false);
public static void PreventPowerSave()
{
(new TaskFactory()).StartNew(() =>
{
SetThreadExecutionState(
EXECUTION_STATE.ES_CONTINUOUS
| EXECUTION_STATE.ES_DISPLAY_REQUIRED
| EXECUTION_STATE.ES_SYSTEM_REQUIRED);
_event.WaitOne();
},
TaskCreationOptions.LongRunning);
}
public static void Shutdown()
{
_event.Set();
}
}
}