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

本文关键字:速度 执行 事件 非常 | 更新日期: 2023-09-27 18:16:55

我正在编写一个具有全局鼠标和键盘钩子的程序。该程序将记录用户的输入,当他们按下录制按钮,将停止录制一旦他们按下停止按钮。我用秒表来计算每个事件的时间跨度,因为这似乎是最准确的方法。

下面是用户记录的事件的一小段:

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和秒表的Elapsed time,但这将占用CPU很多。你们会怎么做才能准确地重现事件?我是在浪费时间在电脑上寻找如此精确的东西吗?

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

将计时器分辨率提高到1ms(这是最大值)。然后使用任何您喜欢的计时方法(计时器、睡眠、事件等)来获得1ms的精度。1000Hz对于任何针对人类感知的东西来说应该足够了。

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

他们只是使用环境。TickCount,用这种方式记录它。每次鼠标/键盘事件发生时,它们将其保存到一个列表中,并带有tick计数。然后,为了回放事件,它们只需在后台线程中循环遍历列表,并休眠每个事件的长度。

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;
        }
    }
}