Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF keyDown response time accuracy

Tags:

c#

.net

wpf

I'm developing an application in which user can see something and has to react by clicking a key on the keyboard. Reaction time is crucial and the more accurate the better it is.

I wrote sample app inf WPF only a few lines of code to test default settings:

namespace Test
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    private Stopwatch sw; 
    public MainWindow()
    {
        InitializeComponent();
        sw = new Stopwatch();
        sw.Start();
        this.KeyDown += OnKeyDown;
    }

    private void OnKeyDown(object sender, KeyEventArgs keyEventArgs)
    {
        sw.Stop();

        lbl.Content = sw.ElapsedMilliseconds;
        sw.Restart();
    }
  }
}

lbl is a just simple label.

What is strange is that when I press for example space and hold it the value of the lbl changes in the range: 30-33.

So I cant predict what is the response accuracy? Is it impossible to have for example 1 ms accuracy? User hits space and at the same time (for example 1 ms accuracy) I can handle it in the event handler?

The main question is:

let's say I have a key-down event handler:

Test_KeyDown(object sender, KeyEventArgs keyEventArgs)
{
   time = stopwatch.elapsed();
   stopwatch.Restart();
}

what is the minimum value of "time" that can possibly occur? Can I be sure that the time value is accurate to 1 ms? In this method, I start the stopwatch but then I have to wait - how long - for the GUI to refresh?

like image 764
gruber Avatar asked Oct 09 '13 23:10

gruber


1 Answers

Your test is certainly invalid, it just measures the keyboard repeat rate as pointed out by several other contributors. But it is useful for its unintended benefit, you can actually see that you won't have a problem with the keyboard.

Most events in Windows occur at a rate that's determined the by the clock interrupt rate. Which by default ticks 64 times per second, once every 15.625 milliseconds. That wakes up the kernel and it goes looking to see if something needs to be done, looking for work to pass to a processor core. Most typically there's nothing to do and the core is shutdown with a HLT instruction. Until the next interrupt occurs.

So a concern would be that your test could never be more accurate than 15.625 milliseconds. And your observation matches, by accident, what you see was twice that number. But that's not actually the case and you can use your program to see that. Use Control Panel + Keyboard and tweak the Repeat Rate slider. Note how you can adjust it and get your number to change to values that are not a multiple of 15.625.

This is not entirely an accident, the keyboard controller also generates an interrupt, just like the clock does. You have positive proof that this interrupt itself is already good enough to get your program to re-activate. And you can tell that the keyboard controller itself is fast enough scanning the keyboard matrix. Your error bar from the keyboard won't be larger than +/- 2 msec, about the noise you see in the displayed number. In case you have a keyboard that scans slower, you can eliminate it with this test.


The far bigger concern you have is the video. The video adapter typically refreshes an LCD monitor at 60 updates per second. So worst case, the test subject would not be able to physically see the image for 17 msec. And LCD monitors themselves are not that fast either, the cheap ones have a response time of 16 msec or worse. A side-effect of the Crystal in the Liquid not being able to flip fast enough.

Eliminating the refresh rate error requires that you program synchronizes with the vertical blanking interval. Something you can do with DirectX. You can find upscale LCD monitors that have response times of about 4 msec, popular with gamers.

like image 92
Hans Passant Avatar answered Oct 10 '22 13:10

Hans Passant