以非常快速、精确和准确的速率执行事件

Executing events at very fast, precise, and accurate rates

我正在制作一个带有全局鼠标和键盘挂钩的程序。该程序将在用户按下录制按钮时记录用户的输入,并在用户按下停止按钮后停止录制。我使用秒表获取每个事件的时间跨度,因为这似乎是最准确的方法。

以下是用户录制的一小段事件:

01:45:20 - Time: 00:00:03.7028259 - Mousemove
01:45:20 - Time: 00:00:03.7190386 - Mouseleftdown
01:45:20 - Time: 00:00:03.7363274 - Mousemove
01:45:20 - Time: 00:00:03.7431332 - Mousemove
01:45:20 - Time: 00:00:03.7519057 - Mousemove
01:45:20 - Time: 00:00:03.7594302 - Mouseleftup

如您所见,有些事件事件相隔将近 8 毫秒(这似乎是我可以在每个事件之间获得的最小时间量)。

用户可以按下播放按钮,他们的录音将开始播放。起初,我查看了 Timer 组件,因为它似乎非常适合这种情况。但是,该组件相当不准确,所以我想我会在这里问。我考虑过创建一个带有秒表和 while 循环的新线程的想法,该线程将比较事件 TimeSpans 和秒表的运行时间,但这会占用 CPU 很多。你们会怎么做才能准确重播这些事件?我是在浪费时间在桌面上寻找如此准确的东西吗?

看看这个图书馆:http://www.codeproject.com/Articles/28064/Global-Mouse-and-Keyboard-Library

他们只是使用 Environment.TickCount 并以这种方式跟踪它。每次发生 mouse/keyboard 事件时,他们都会将其保存到一个列表中,并附上滴答计数。然后,为了回放事件,他们只需在后台线程中循环遍历列表并在每个事件的长度内休眠。

void mouseHook_MouseMove(object sender, MouseEventArgs e)
{

    events.Add(
        new MacroEvent(
            MacroEventType.MouseMove,
            e,
            Environment.TickCount - lastTimeRecorded
        ));

    lastTimeRecorded = Environment.TickCount;

}

void mouseHook_MouseDown(object sender, MouseEventArgs e)
{

    events.Add(
        new MacroEvent(
            MacroEventType.MouseDown,
            e,
            Environment.TickCount - lastTimeRecorded
        ));

    lastTimeRecorded = Environment.TickCount;

}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    foreach (MacroEvent macroEvent in events)
    {
        Thread.Sleep(macroEvent.TimeSinceLastEvent);

        switch (macroEvent.MacroEventType)
        {
            case MacroEventType.MouseMove:
                {
                    MouseEventArgs mouseArgs = (MouseEventArgs)macroEvent.EventArgs;
                    MouseSimulator.X = mouseArgs.X;
                    MouseSimulator.Y = mouseArgs.Y;
                }
                break;
            case MacroEventType.MouseDown:
                {
                    MouseEventArgs mouseArgs = (MouseEventArgs)macroEvent.EventArgs;
                    MouseSimulator.MouseDown(mouseArgs.Button);
                }
                break;
            default:
                break;
        }
    }
}

将计时器分辨率提高到 1 毫秒(最大值)。然后使用您喜欢的任何计时方法(计时器、睡眠、事件……)以获得 1 毫秒的精度。 1000Hz 应该足以满足任何针对人类感知的需求。