如何获取线程执行状态



在Windows上,每个线程都有一个执行状态,可以通过调用SetThreadExecutionState来设置。例如,如果线程调用:

SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED)

则在该线程更改其执行状态或终止之前,Windows不会关闭显示。

可以从C#访问:

[DllImport("kernel32.dll", SetLastError = true)] SetThreadExecutionState(...)

但是,当SetThreadExecutionState设置执行状态时,似乎没有任何等效的GetThreadExecutionStateAPI。kernel32.dll导出SetThreadExecutionState而不导出GetThreadExecutionState。我试过了:

[DllImport("kernel32.dll", SetLastError = true)] internal static extern uint GetThreadExecutionState();

但我得到了一个System.EntryPointNotFoundException,说GetThreadExecutionStatekernel32.dll中不存在。

那么,我如何在不更改当前线程的情况下找到它的执行状态呢?

SetThreadExecutionState做两件不同的事情:

  1. 更改当前线程的执行状态标志
  2. 重置系统范围内的空闲定时器

当您通过ES_CONTINUOUS时,它会执行(1(;否则是(2(。

因此,如果不将ES_CONTINUOUS作为输入传递,它将不会更改当前线程的执行标志,只会重置空闲计时器。

当复位空闲定时器时,ES_SYSTEM_REQUIRED告诉它复位系统空闲定时器,ES_DISPLAY_REQUIRED告诉它复位显示器空闲定时器。如果你没有通过ES_SYSTEM_REQUIREDES_DISPLAY_REQUIRED,它不会重置任何空闲定时器。

换句话说,SetThreadExecutionState(0)本质上是一个无操作——它不会更改线程的执行标志,也不会重置任何空闲定时器。但它确实做了一些有用的事情——它返回线程执行标志的当前值。

所以,你要找的GetThreadExecutionState不存在,但你不需要它,因为SetThreadExecutionState(0)是等价的。

请注意,返回值始终包括ES_CONTINUOUS。因此,如果您的线程没有设置任何执行状态标志SetThreadExecutionState(0) == ES_CONTINUOUS。然而,假设当前线程设置了ES_SYSTEM_REQUIRED,那么SetThreadExecutionState(0) == ES_CONTINUOUS|ES_SYSTEM_REQUIRED

如果函数失败,返回值不包括ES_CONTINUOUS,则返回0。据我所知,函数失败的唯一方法是传递一些不受支持的标志。

请注意,除了每个线程的执行状态标志外,还有系统范围的标志。您可以使用CallNtPowerInformationSystemExecutionState信息级别来获得这些信息。如果任何线程具有SetThreadExecutionState(ES_CONTINUOUS|ES_SYSTEM_REQUIRED),则在SystemExecutionState中将设置ES_SYSTEM_REQUIRED。在我自己的测试中,其他每线程执行状态标志似乎都不会影响系统执行状态。

最新更新