1

I've got this code:

while(MouseKeyboardStateTest.Keyboard.IsKeyDown(Keys.Space))
{
    Keyboard.KeyPress(Keys.A);
    Thread.Sleep(asChecker.currentDelay);
    for (int i = 0; i <= asChecker.currentMouseClicks; i++)
    {
        Mouse.PressButton(Mouse.MouseKeys.Right);
        Thread.Sleep(globalMouseDelay);
    }
}

And it works fine, with the problem being - Thread.Sleep is not accurate, and the delay is not always the same. Is there any other way I could approach this issue, to make it exact to at least ~10ms?

user247702
  • 23,641
  • 15
  • 110
  • 157
P Sawicki
  • 189
  • 1
  • 2
  • 9
  • 4
    It is *exactly* as accurate as it needs to be. The OS thread scheduler only looks for threads that are ready to run at the "heart beat", the clock tick interrupt. It normally ticks 64 times per second. Tends to be 100 times when you have a browser opened. You cannot assume that your thread actually gets the processor when the sleep time expired, it has to compete with other threads that want service as well. Using Thread.Priority can help to take an unfair share. To get a guarantee that it will be 10 msec instead of 15.625 you need to pinvoke timeBeginPeriod(). – Hans Passant Nov 07 '18 at 17:10

1 Answers1

2

Don't use Thread.Sleep at all!

Set the KeyPreview of the form to true and use the key events of the form.

This will allow you to get notified of key events without lag and without a loop freezing the UI.

See also this answer to Winforms : Intercepting Mouse Event on Main Form first, not on Controls.

You also might use a gaming API instead. Those allow you to react on mouse and key events very fast and not tied to controls. They also allow you to detect simultaneous key presses.


Since you are not doing this in an UI (according to your comment), I suggest a different approach:

In a game you are usually using a gaming loop that loops as fast as possible, without any Thread.Sleep delay. At every loop you check the current state of the input (keyboard, mouse, joystick) and update the game state and display accordingly.

At every loop save the current time with DateTime.UtcNow (faster than DateTime.Now) and check the time elapsed since an action happened to know whether the required delay has been reached.

If DateTime is not accurate enough, use the StopWatch class. See: Precision and accuracy of DateTime.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • I'm not using any UI, the delay is there as it's doing action in game and it needs to have a certain delay. – P Sawicki Nov 07 '18 at 17:23
  • Since you reopened and answered the question, please edit the question with a better title. As it is now, people who arrive at this question will likely have quite a different problem than what you answered here. – user247702 Nov 08 '18 at 13:16