c# - C# keybd_event 和 mouse_event 占用过多 CPU
问题描述
我尝试自己编写宏记录器。我很难找出为什么我的程序占用这么多 CPU。录制程序时只需要大约 0.2% 的 cpu 使用率。在播放时,它的使用率高达 25% 左右。
为了模拟键盘输入,我将此代码称为打开一个新任务的代码。
var kTask = new Task(() => new KeyboardTask(keys_stop[index], keys[index]));
kTask.Start();
任务调用这个类:
class KeyboardTask
{
[DllImport("user32.dll")] static extern short VkKeyScan(char ch);
// Import the user32.dll
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
// Declare some keyboard keys as constants with its respective code
// See Virtual Code Keys: https://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
public const int VK_RCONTROL = 0xA3; //Right Control key code
public const int VK_LCONTROL = 0xA2; //Left Control key code
public const int VK_LSHIFT = 0xA0;
public const int VK_RSHIFT = 0xA1;
byte key;
long cooldown;
long cooldown_time = 500;
long delay;
long delay_now;
bool first_press = false;
DateTime lastCooldown;
DateTime start;
DateTime stop;
TimeSpan ts;
public KeyboardTask(long delay, Key run_key)
{
key = (byte)KeyInterop.VirtualKeyFromKey(run_key);
lastCooldown = DateTime.Now;
this.delay = delay;
runOtherKeys();
if (run_key == Key.LeftShift || run_key == Key.RightShift)
{
runShift();
}
else if (run_key == Key.LeftCtrl)
{
runCtrl();
}
}
private void runShift()
{
start = DateTime.Now;
while (delay >= delay_now)
{
stop = DateTime.Now;
ts = (stop - start);
delay_now = (long)ts.TotalMilliseconds;
if (!first_press)
{
keybd_event(key, 0, KEYEVENTF_EXTENDEDKEY, 0);
first_press = true;
}
}
keybd_event(VK_LSHIFT, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_RSHIFT, 0x45, KEYEVENTF_KEYUP, 0);
}
private void runCtrl()
{
start = DateTime.Now;
while (delay >= delay_now)
{
stop = DateTime.Now;
ts = (stop - start);
delay_now = (long)ts.TotalMilliseconds;
if (!first_press)
{
keybd_event(VK_LCONTROL, 0x9d, 0, 0);
first_press = true;
}
}
keybd_event(VK_LCONTROL, 0x9d, KEYEVENTF_KEYUP, 0);
}
private void runOtherKeys()
{
start = DateTime.Now;
while (delay >= delay_now)
{
stop = DateTime.Now;
ts = (stop - start);
delay_now = (long)ts.TotalMilliseconds;
if (first_press)
{
cooldown = getCooldown();
if (cooldown >= cooldown_time)
{
lastCooldown = DateTime.Now;
cooldown_time = 33;
keybd_event(key, 0x45, 0, 0);
keybd_event(key, 0x45, KEYEVENTF_KEYUP, 0);
}
}
else
{
lastCooldown = DateTime.Now;
keybd_event(key, 0x45, 0, 0);
keybd_event(key, 0x45, KEYEVENTF_KEYUP, 0);
first_press = true;
}
}
keybd_event(key, 0x45, KEYEVENTF_KEYUP, 0);
}
private long getCooldown()
{
DateTime cooldown_stop = DateTime.Now;
TimeSpan cooldown_timespan = (cooldown_stop - lastCooldown);
return (long)cooldown_timespan.TotalMilliseconds;
}
}
为了模拟鼠标输入,我在这里有这个代码:
public void Start()
{
Task.Run(() => runRecordMouse());
}
private void runRecordMouse()
{
DateTime start = DateTime.Now;
DateTime stop;
TimeSpan ts;
long time;
int count = 0;
int max = x_arr.Length;
long delay = delay_arr_mouse[count];
while (count < max)
{
stop = DateTime.Now;
ts = (stop - start);
time = (long)ts.TotalMilliseconds;
if (delay <= time)
{
performMouseEvent(count);
count++;
if (count != max) delay = delay_arr_mouse[count];
start = DateTime.Now;
}
}
}
private void performMouseEvent(int pos)
{
mouse_button = mouse_click_arr[pos];
x = x_arr[pos];
y = y_arr[pos];
if (mouse_button_pre != mouse_button && mouse_button_pre == 1)
{
mouse_event(MOUSEEVENTF_LEFTUP, x, y, 0, 0);
}
if (mouse_button_pre != mouse_button && mouse_button_pre == 2) mouse_event(MOUSEEVENTF_RIGHTUP, x, y, 0, 0);
switch (mouse_button)
{
case 0:
SetCursorPos(x, y); //move
break;
case 1:
if (mouse_button_pre == mouse_button)
{
Drag(x_arr[pos - 1], y_arr[pos - 1], x, y); //left Click drag
}
else
{
mouse_event(MOUSEEVENTF_LEFTDOWN, x, y, 0, 0); //left Click
}
break;
case 2:
mouse_event(MOUSEEVENTF_RIGHTDOWN, x, y, 0, 0); //right Click
break;
}
mouse_button_pre = mouse_button;
}
private static void Drag(int xStart, int yStart, int x, int y)
{
x = x - xStart;
y = y - yStart;
SetCursorPos(xStart, yStart);
mouse_event(MOUSEEVENTF_MOVE, x, y, 0, 0);
}
它是用 C# .NET Framework 编写的。
我的电脑: CPU:AMD Ryzen 5 3600 内存:32 GB GPU:AMD Radeon RX 5700
解决方案
我刚刚添加
Thread.Sleep(1);
到所有的 while 循环,现在程序只需要大约 0.5% 的 cpu 使用率。
推荐阅读
- android - 为什么应用开发者限制奖励视频广告的数量,用户每天可以查看?
- ios - UIbutton点击问题 - Swift
- r - 地理编码失败,状态为 REQUEST_DENIED,位置 =“澳大利亚”,在 R 中使用 ggmap
- python - Anaconda python ver5.3永远挂在更新
- r - 为什么文字会出现在图例中?
- ruby-on-rails - 解析复杂的哈希并返回对键的更改
- java - 如何避免 java.lang.StackOverflowError?
- python - Python3判断两个字典是否相等
- php - 如何在我的查询中使用函数 max current-date
- python - python中的嵌套列表包含单个字符串而不是单个字母