2013-10-09 17 views
9

Sto sviluppando un'applicazione in cui l'utente può vedere qualcosa e deve reagire facendo clic su un tasto sulla tastiera. Il tempo di reazione è cruciale e più preciso è, meglio è.WPF keyDown precisione i tempi di risposta

ho scritto campione app inf WPF solo poche righe di codice per testare le impostazioni predefinite:

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 è un'etichetta solo semplice.

Ciò che è strano è che quando preme per esempio lo spazio e lo tengo il valore delle variazioni lbl nell'intervallo: 30-33.

così non posso prevedere quello che è l'accuratezza di risposta? È impossibile avere ad esempio 1 ms di precisione? L'utente colpisce lo spazio e allo stesso tempo (ad esempio 1 ms di accuratezza) Posso gestirlo nel gestore di eventi?

La domanda principale è:

diciamo che ho un gestore di eventi chiave-down:

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

qual è il valore minimo di "tempo" che può eventualmente verificarsi? Posso essere sicuro che il valore temporale sia accurato a 1 ms? In questo metodo, ho avviare il cronometro ma poi ho dovuto aspettare - per quanto tempo - per la GUI per aggiornare?

+0

Non sai cosa stai cercando di misurare lì, né come lo fai. 'KeyDown' non viene sollevato continuamente mentre il tasto è premuto (credo che sarebbe' KeyPress') quindi tenere la barra spaziatrice non dovrebbe aggiornare l'etichetta più di una volta, vero? Se si intende che si tiene la barra spaziatrice prima di mostrare la finestra, quindi si confronta il codice tra il costruttore fino a quando la finestra è finalmente attiva e pompa gli eventi. – jods

+0

Per quanto ne so, l'evento è il più veloce possibile e funziona praticamente allo stesso modo delle altre app di Windows: la chiave down è gestita dal sistema operativo, che invia un messaggio alla coda dei messaggi della finestra, che viene quindi pompato e l'evento corrispondente viene sollevato sul controllo focalizzato. La precisione è abbastanza buona se confrontata con i tempi di reazione umani, a meno che tu non lavori sul tuo thread UI. – jods

+0

La velocità di un tasto premuto dipenderà dalla configurazione di Windows della frequenza di ripetizione dei tasti. http://windows.microsoft.com/is-is/windows-xp/help/adjust-the-character-repeat-rate – Tony

risposta

5

primo luogo, se Stopwatch.IsHighResolution è true, quindi Stopwatch utilizza QueryPerformanceCounter, e può misurare intervalli di tempo con risoluzione < 1 ms.

secondo luogo, quando si preme e si tiene premuto il tasto spazio, Windows inizia a inviare messaggi WM_KEYDOWN più volte, e il cronometro misurerà l'intervallo tra questi messaggi. Questo intervallo è determinato dalla chiave di registro HKCU\Control Panel\Keyboard\KeyboardSpeed.

valore predefinito di IT è 31, che è la velocità di ripetizione più veloce, il che significa circa 30 caratteri al secondo. Ecco perché hai misurato circa 1000/30 = intervalli di 33 ms.

Se si imposta su 0, ovvero sulla velocità di ripetizione più bassa, che significa circa 2 caratteri al secondo, è necessario misurare ca. Intervalli di 500 ms. Ho testato il tuo codice con questa impostazione e ho ricevuto 500 ms. (Non dimenticare di riavviare Windows dopo aver cambiato KeyboardSpeed!)

È necessario catturare un singolo evento keydown, non eventi ripetuti, quindi non è necessario modificare l'impostazione KeyboardSpeed. Il tuo programma dovrebbe mostrare l'oggetto all'utente, avviare il cronometro e fermarlo se si verifica un evento keydown. ElapsedMilliseconds darà il tempo di reazione. Misuralo più volte e usa la media.

Il problema è che, anche se il tempo misurato con precisione QueryPerformanceCounter, c'è un ritardo causato dalla tastiera e Windows stesso che aumenterà il tempo di reazione misurato. Inoltre, il ritardo non è costante: se Windows è occupato nel momento in cui deve gestire l'evento keydown, il ritardo sarà maggiore. Quindi se prendi sul serio l'attività, dovresti calibrare il tuo programma.

Voglio dire, dovresti comprare o costruire un piccolo dispositivo elettronico basato su microcontrollore, che accende un LED e rileva il tempo trascorso tra l'accensione del LED e l'utente che preme un pulsante.Effettuare le misurazioni del tempo di reazione 10-20 (più è e meglio è) con questo dispositivo e con la stessa persona di prova, eseguire altre 10-20 misurazioni con il programma. La differenza tra i due ti darà il ritardo causato dalla tastiera e da Windows. Questa differenza può essere sottratta dal tempo di reazione misurato dal programma.

(Si potrebbe chiedere, perché non si dovrebbe utilizzare il dispositivo elettronico piccolo ma preciso anziché un'applicazione Windows. In primo luogo, la produzione e la vendita di software è molto più semplice ed economica rispetto alla produzione e alla vendita di hardware. può essere complesso (es. scacchiera) e gli oggetti complessi possono essere resi in modo molto più efficiente su un PC.)

+0

Potrei suggerire di alterare il registro degli utenti potrebbe non essere il modo migliore per farlo, ma semplicemente leggendo quel valore e rilevando l'azienda della chiave specificata. – SeToY

+0

@SeToY Ho modificato il registro solo per verificare la mia ipotesi sull'intervallo di 33 ms che l'OP misurava quando lo spazio veniva premuto continuamente. La precisione della misurazione dell'intervallo di tempo non è correlata a questo, quindi l'OP non dovrebbe modificare il registro dell'utente. – kol

11

Il test non è certamente valido, misura solo la frequenza di ripetizione della tastiera come sottolineato da diversi altri contributori. Ma è utile per il suo beneficio indesiderato, puoi effettivamente vedere che non avrai problemi con la tastiera.

La maggior parte degli eventi di Windows si verifica a una velocità determinata dalla frequenza di interruzione dell'orologio. Che di default fa tic tac 64 volte al secondo, una volta ogni 15.625 millisecondi. Questo risveglia il kernel e cerca di vedere se qualcosa deve essere fatto, cercando il lavoro da passare al core del processore. Di solito non c'è niente da fare e il core è spento con un'istruzione HLT. Fino alla prossima interruzione.

Quindi una preoccupazione sarebbe che il test non potrebbe mai essere più preciso di 15,625 millisecondi. E la tua osservazione corrisponde, per caso, a quello che vedi è il doppio di quel numero. Ma in realtà non è così e puoi usare il tuo programma per vederlo. Utilizzare il Pannello di controllo + Tastiera e regolare il cursore Velocità di ripetizione. Nota come puoi regolarlo e ottenere il tuo numero per cambiare a valori che non sono multipli di 15.625.

Questo non è interamente un incidente, il controller della tastiera genera anche un interrupt, proprio come fa l'orologio. Hai la prova positiva che questo stesso interrupt è già abbastanza buono da far riattivare il tuo programma. E puoi dire che lo stesso controller della tastiera è abbastanza veloce da scansionare la matrice della tastiera. La tua barra di errore dalla tastiera non sarà più grande di +/- 2 msec, a proposito del rumore che vedi nel numero visualizzato. Se hai una tastiera che esegue la scansione più lentamente, puoi eliminarla con questo test.


La preoccupazione più grande che si ha è il video. La scheda video in genere aggiorna un monitor LCD a 60 aggiornamenti al secondo. Quindi, nel peggiore dei casi, il soggetto del test non sarebbe in grado di fisicamente vedere l'immagine per 17 msec. Anche i monitor LCD non sono così veloci, quelli più economici hanno un tempo di risposta di 16 msec o peggio. Un effetto collaterale del Crystal in the Liquid non è in grado di capovolgere abbastanza velocemente.

L'eliminazione dell'errore di frequenza di aggiornamento richiede la programmazione della sincronizzazione con vertical blanking interval. Qualcosa che puoi fare con DirectX. È possibile trovare monitor LCD di alto livello che hanno tempi di risposta di circa 4 msec, popolari con i giocatori.

1

Vorrei mettere in evidenza un altro strumento per rintracciare i tempi qui. Dal momento che stai considerando il test della risposta dell'applicazione, e come qualcuno ha menzionato questo riguarda i messaggi del sistema operativo, puoi utilizzare Spy ++ per vedere i tempi di questi messaggi. Ho copiato l'output di premere spazio in una finestra che stavo ascoltando solo per i messaggi della tastiera, dopo aver acceso tutto l'output. Ho premuto lo spazio una volta e rilasciato il più rapidamente possibile su una tastiera USB che passa attraverso una docking station. Si può vedere che ci sono voluti ~ .05ms per elaborare verso il basso.

<00001> 00090902 P WM_KEYDOWN nVirtKey:VK_SPACE cRepeat:1 ScanCode:39 fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000020 lParam:00390001 time:1:07:38.116 point:(183, 290)] 
<00002> 00090902 P WM_CHAR chCharCode:'32' (32) cRepeat:1 ScanCode:39 fExtended:0 fAltDown:0 fRepeat:0 fUp:0 [wParam:00000020 lParam:00390001 time:1:07:38.116 point:(183, 290)] 
<00003> 00090902 P WM_KEYUP nVirtKey:VK_SPACE cRepeat:1 ScanCode:39 fExtended:0 fAltDown:0 fRepeat:1 fUp:1 [wParam:00000020 lParam:C0390001 time:1:07:38.163 point:(183, 290)] 

Spy ++ è uno strumento fornito con Visual Studio. Puoi trovarlo allo C:\Program Files\Microsoft Visual Studio XYZ\Common7\Tools\spyxx.exe dove XYZ è 8, 9.0 e 10.0 che posso confermare.

Cosa si potrebbe fare per testare ulteriormente i tempi sarebbe avere Spy ++ in ascolto per i comandi della tastiera e WM_PAINT o qualcosa del genere, per vedere quanto velocemente il programma risponde a un messaggio della tastiera con la sua modifica dell'interfaccia utente.

Ad esempio, il seguente è il registro pulito dopo aver Calcolatrice con 3+3 già, quindi premendo Enter. Vedete che la calcolatrice è stata in grado di calcolare e visualizzare prima del .062ms richiesto tra KeyDown e KeyUp da elaborare.

<00001> 00090902 P WM_KEYDOWN nVirtKey:VK_RETURN cRepeat:1 ScanCode:1C fExtended:1 fAltDown:0 fRepeat:0 fUp:0 [wParam:0000000D lParam:011C0001 time:1:19:12.539 point:(179, 283)] 
<00002> 00090902 S WM_PAINT hdc:00000000 [wParam:00000000 lParam:00000000] 
<00003> 00090902 R WM_PAINT lResult:00000000 
<00004> 00090902 S WM_PAINT hdc:00000000 [wParam:00000000 lParam:00000000] 
<00005> 00090902 R WM_PAINT lResult:00000000 
<00006> 00090902 S WM_PAINT hdc:00000000 [wParam:00000000 lParam:00000000] 
<00007> 00090902 R WM_PAINT lResult:00000000 
<00008> 00090902 S WM_PAINT hdc:00000000 [wParam:00000000 lParam:00000000] 
<00009> 00090902 R WM_PAINT lResult:00000000 
<00010> 00090902 P WM_KEYUP nVirtKey:VK_RETURN cRepeat:1 ScanCode:1C fExtended:1 fAltDown:0 fRepeat:1 fUp:1 [wParam:0000000D lParam:C11C0001 time:1:19:12.601 point:(179, 283)] 

edit- In Spy ++ Suggerisco di accedere a Opzioni di registrazione che mostra la finestra di dialogo Opzioni messaggio. Vai alla scheda Messaggi, fai clic su Cancella tutto, seleziona "Tastiera", quindi scorri la casella di riepilogo e seleziona WM_PAINT. In questo modo hai solo i messaggi desiderati, altrimenti verrai inondato da essi.

Problemi correlati