【问题标题】:SetThreadExecutionState(ES_SYSTEM_REQUIRED) does not prevent system sleep on Windows 11SetThreadExecutionState(ES_SYSTEM_REQUIRED) 不会阻止 Windows 11 上的系统睡眠
【发布时间】:2022-06-30 12:53:29
【问题描述】:

在我的文件传输应用程序 (WinSCP) 中,我使用 SetThreadExecutionState(ES_SYSTEM_REQUIRED) 来防止系统在文件传输过程中进入睡眠模式。但这在 Windows 11 上不再适用。

我没有找到任何关于应用程序在 Windows 11 上阻止睡眠模式的不同要求的参考。

我的应用程序是 C++ Win32 应用程序。但我可以用一个简单的 .NET 5 WinForms C# 应用程序重现同样的问题。

private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Label label1;
public enum EXECUTION_STATE : uint
{
    ES_SYSTEM_REQUIRED = 0x00000001
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint SetThreadExecutionState(EXECUTION_STATE esFlags);

// The timer ticks every second.
private void timer1_Tick(object sender, EventArgs e)
{
    label1.Text = (int.Parse(label1.Text) + 1).ToString();
    SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
}

只要应用程序在 Windows 10 上运行,系统就永远不会进入睡眠模式。但 Windows 11 会按计划进入睡眠状态。

Windows 11 上的 Windows 文件资源管理器在传输文件时成功防止睡眠。因此,阻止 Windows 11 进入睡眠模式并非不可能。

为什么SetThreadExecutionState(ES_SYSTEM_REQUIRED) 在 Windows 11 上不再工作? Windows 11 上是否有用于此任务的不同 API?

【问题讨论】:

  • @HansPassant 我以前看过那个帖子。但我相信这主要是关于硬件和完全相反的问题(计算机不会进入或从睡眠中醒来)。还是我错过了线程的某些特定相关部分?
  • 好吧,我可以告诉你,我的 8.1 平板电脑连接待机忽略了大多数本应保持正常运行的电源 API,并在超时后进入睡眠状态。
  • 在这个例子中你的计时器多久计时一次?
  • @MartinPrikryl 你试过添加ES_CONTINUOUS 标志吗?

标签: .net windows winapi kernel32 sleep-mode


【解决方案1】:

似乎SetThreadExecutionState(ES_SYSTEM_REQUIRED)“重置空闲计时器”API(即没有 ES_CONTINUOUS 标志)在 Windows 11 中被破坏了。

ES_CONTINUOUS API 有效。所以我不得不重新设计我的应用程序来使用那个。由于我的应用程序可以有多个线程,每个线程都执行冗长的操作,因此在操作期间从每个线程中重复调用SetThreadExecutionState(ES_SYSTEM_REQUIRED) 更方便。

现在我必须有一个单独的线程,其唯一目的是向系统报告应用程序状态。第一次SetThreadExecutionState(ES_SYSTEM_REQUIRED) 之前会被任何线程调用,现在触发“状态线程”调用SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_CONTINUOUS)。进一步调用只是重置内部 5 秒计时器。如果该计时器最终到期,状态线程将调用SetThreadExecutionState(ES_CONTINUOUS)

【讨论】:

    【解决方案2】:

    根据SetThreadExecutionState

    在没有 ES_CONTINUOUS 的情况下调用 SetThreadExecutionState 简单 重置空闲计时器;保持显示器或系统正常工作 状态,线程必须定期调用 SetThreadExecutionState。

    或者,如文档示例所示,调用 SetThreadExecutionState:

    // Enable away mode and prevent the sleep idle time-out.
    //
    SetThreadExecutionState(ES_CONTINUOUS | ES_AWAYMODE_REQUIRED);
    
    //
    // ...
    //
    
    //
    // Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally.
    //
    SetThreadExecutionState(ES_CONTINUOUS);
    

    【讨论】:

    • 谢谢。虽然我确实“定期调用 SetThreadExecutionState”。 + 如果我正确理解文档,您可以通过重复调用SetThreadExecutionState 而不使用ES_CONTINUOUS 来保持系统运行;或使用ES_CONTINUOUS 调用一次。因此,虽然您的 ES_CONTINUOUS 代码也应该可以工作(而且它确实似乎可以工作),但它并不能解释为什么我的代码不能。或者您有任何理由相信没有 ES_CONTINUOUS 的 API 在 Windows 11 上不再有效?
    • 就我而言,ES_SYSTEM_REQUIRED 通过重置系统空闲计时器一次来强制系统处于工作状态。
    • 是的,这就是为什么我在示例代码中每秒都在计时器上调用它。这在 Windows 10 上按预期工作。
    • @MartinPrikryl 我转载了,我正在调查这种行为。
    • “离开模式只能由媒体录制和媒体分发应用程序使用”
    猜你喜欢
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    相关资源
    最近更新 更多