为何任务管理器激活时GetAsyncKeyState()性能骤降百倍?
我在代码中频繁使用GetAsyncKeyState()测试视觉及速度相关特性时,偶然发现当Taskmgr.exe激活并处于前台时,该函数的运行速度会下降约100倍。
为验证这个现象,我编写了一个测试程序,通过无限循环检测按键状态,代码如下:
#include <iostream> #include <windows.h> #include <chrono> using std::chrono::high_resolution_clock; using std::chrono::duration; #define IS_PRESSED( vk ) ( GetAsyncKeyState( vk ) & 0x8000 ) // 观察:Taskmgr.exe激活时速度骤降 #define IS_ACTIVE( vk ) ((GetKeyState(vk) & 0x0001) != 0) int main() { std::cout << "Hello World!\n"; auto t1 = high_resolution_clock::now(); int i = 0; while (!IS_PRESSED(VK_ESCAPE)) // 观察:Taskmgr激活时速度下降约100倍 // while (!IS_ACTIVE(VK_ESCAPE)) // 无异常,无时间副作用 { i++; if (i % 100000 == 0) { // 打印速度 auto t2 = high_resolution_clock::now(); duration<double, std::milli> ms_ElaspedTime = t2 - t1; /* 获取毫秒数(double类型) */ std::cout << "Speed: " << ms_ElaspedTime.count() << " ms / 100'000 loops" << std::endl; t1 = high_resolution_clock::now(); } } }
测试结果如下:
Speed: 0.445 ms / 100'000 Loops(正常状态)
Speed: 140.577 ms / 100'000 Loops !! (TaskMgr.exe处于前台激活状态)
请问有人能解释这一问题吗?
解释
这是因为任务管理器(Taskmgr.exe)在前台激活时会启用高优先级的系统监控机制,同时Windows会对它施加特殊的输入处理限制,具体原因如下:
输入钩子与资源抢占:
GetAsyncKeyState()依赖系统输入队列和全局键盘状态快照。当任务管理器处于前台时,它会注册高优先级的输入钩子或监控线程,抢占大量系统资源,导致普通进程调用GetAsyncKeyState()时需要等待系统完成对任务管理器的输入处理,大幅增加调用延迟。系统特权与调度倾斜:任务管理器属于系统级进程,拥有比普通用户进程更高的优先级。当它处于前台时,Windows进程调度器会优先分配更多CPU时间片给它,同时限制普通进程对输入子系统的访问频率,避免恶意程序通过高频按键检测干扰系统监控工具。
函数实现机制差异:
GetKeyState()仅读取当前线程的键盘状态缓存,无需跨进程访问系统全局输入状态,因此不受任务管理器前台状态的影响;而GetAsyncKeyState()需要实时查询系统全局的按键状态,这一步在任务管理器激活时会被系统限流。
内容的提问来源于stack exchange,提问作者Tom Tom

