C# 从windows服务调用SetThreadExecutionState时,SetThreadExecutionState不工作

C# 从windows服务调用SetThreadExecutionState时,SetThreadExecutionState不工作,c#,windows,windows-services,C#,Windows,Windows Services,我希望防止系统从windows服务进入睡眠/休眠状态。 我正在调用SetThreadExecutionState函数来完成此操作。 但似乎没有效果。 我只想知道函数SetThreadExecutionState是否适用于windows服务。如果没有,还有什么替代方法 下面是我正在使用的C代码。我在Onstart服务方法上调用它 [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] static exter

我希望防止系统从windows服务进入睡眠/休眠状态。 我正在调用
SetThreadExecutionState
函数来完成此操作。 但似乎没有效果。 我只想知道函数
SetThreadExecutionState
是否适用于windows服务。如果没有,还有什么替代方法

下面是我正在使用的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)
}
调用SetThreadExecutionState而不使用ES_CONTINUOUS只会重置空闲计时器;要使显示器或系统保持工作状态,线程必须定期调用SetThreadExecutionState

()


你需要时不时地调用这个函数。这不是一个“即发即忘”的问题。

SetThreadExecutionState仅对调用它的线程有效。如果在工作线程中调用,即使使用ES_CONTINUOUS,一旦工作线程死机,设置将不再有效,然后屏幕保护程序将再次打开

从计时器调用此API将在前一个线程死亡之前唤醒工作线程,从而使其工作


因此,如果您在主线程中调用SetThreadExecutionState,就像在客户端应用程序中调用UI线程一样,您不需要计时器。

这是我的解决方案,希望能有所帮助。似乎在Windows 10上工作。用法:

PowerUtilities.PreventPowerSave()

。。。后来

PowerUtilities.Shutdown()

不意味着可以重新调用

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();
        }
    }
}

它是否返回0?如果是这样,GetLastError()返回什么?@Tony Lee它返回一个非零值。您使用的是什么Windows系统?我正在使用ES_CONTINUOUS标志calling@Prasad是的,你是。每5分钟使用该标志调用一次,它就会工作。因此,如果需要定期调用,这意味着MSDN文档是错误的?或者这种奇怪的5分钟现象只发生在服务上?这个答案中的引语意味着使用
ES_CONTINUOUS
SetThreadExecutionState()
只需要调用一次。OP正确地做到了这一点。但是,他在
OnStart
中调用它,我假设它运行在一个短期线程上,当线程结束时,状态将过期。计时器解决方案使用的线程池线程寿命很长,但这是一个糟糕的解决方案。@KayZed这是一个有趣的理论。你说的是对的;看起来即使只打一次电话也能用,对。最好是在
OnStart
中启动一个新线程,并让它调用
SetThreadExecutionState()
。然后线程应该保持活动状态;为此,可以使用
EventWaitHandle
。在顶部的
中设置它。