9

ユーザーが何かを見ることができ、キーボードのキーをクリックして反応する必要があるアプリケーションを開発しています。反応時間は非常に重要であり、正確であるほど優れています。

デフォルト設定をテストするために、サンプル アプリ inf WPF を数行のコードだけで記述しました。

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シンプルなラベルです。

奇妙なのは、たとえばスペースを押したままにするlblと、範囲の変化の値が 30 ~ 33 になることです。

では、応答精度を予測することはできませんか? たとえば1ミリ秒の精度を持つことは不可能ですか? ユーザーがスペースをヒットすると同時に (たとえば 1 ミリ秒の精度)、イベント ハンドラーでそれを処理できますか?

主な質問は次のとおりです。

キーダウン イベント ハンドラがあるとします。

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

発生する可能性のある「時間」の最小値は? 時間値が 1 ミリ秒まで正確であることを確認できますか? この方法では、ストップウォッチを開始しますが、GUI が更新されるまでどのくらい待つ必要がありますか?

4

3 に答える 3

11

あなたのテストは確かに無効です。他のいくつかの貢献者が指摘したように、キーボードのリピート率を測定するだけです。しかし、それは意図しない利点のために役立ちます.実際には、キーボードに問題がないことがわかります.

Windows のほとんどのイベントは、クロック割り込みレートによって決定されるレートで発生します。デフォルトでは、1 秒あたり 64 回、15.625 ミリ秒ごとに 1 回ティックします。これによりカーネルが起動し、何かを行う必要があるかどうかを確認し、プロセッサ コアに渡す作業を探します。ほとんどの場合、何もすることがなく、コアは HLT 命令でシャットダウンされます。次の割り込みが発生するまで。

したがって、テストが 15.625 ミリ秒よりも正確になることは決してないという懸念があります。そして、あなたの観察は偶然にも一致し、あなたが見たものはその数の 2 倍でした。しかし、実際にはそうではなく、プログラムを使用してそれを確認できます。コントロール パネル + キーボードを使用して、リピート レート スライダーを微調整します。それを調整して、数値を 15.625 の倍数ではない値に変更する方法に注意してください。

これは完全に偶然というわけではありません。キーボード コントローラも時計と同じように割り込みを生成します。この割り込み自体が、プログラムを再アクティブ化するのに十分であるという肯定的な証拠があります。また、キーボード コントローラー自体がキーボード マトリックスをスキャンするのに十分な速さであることがわかります。キーボードからのエラーバーは、表示された数値に見られるノイズについて、+/- 2 ミリ秒よりも大きくなりません。スキャンが遅いキーボードを使用している場合は、このテストで排除できます。


あなたが持っているはるかに大きな懸念はビデオです。通常、ビデオ アダプタは、毎秒 60 回の更新で LCD モニタをリフレッシュします。したがって、最悪の場合、被験者は17 ミリ秒間画像を物理的に見ることができなくなります。また、LCD モニター自体もそれほど高速ではありません。安価なモニターの応答時間は 16 ミリ秒以下です。Crystal in the Liquid が十分な速さでフリップできないという副作用。

リフレッシュ レート エラーをなくすには、プログラムで垂直ブランキング間隔と同期する必要があります。DirectX でできること。ゲーマーに人気の、約 4 ミリ秒の応答時間を持つ高級液晶モニターを見つけることができます。

于 2013-10-13T04:49:20.753 に答える
5

まず、 が の場合Stopwatch.IsHighResolutiontrueStopwatch使用しQueryPerformanceCounter、1 ミリ秒未満の分解能で時間間隔を測定できます。

次に、スペース キーを押したままにすると、Windows は WM_KEYDOWN メッセージを繰り返し送信し始め、ストップウォッチはこれらのメッセージの間隔を測定します。この間隔は、レジストリ キーによって決定されますHKCU\Control Panel\Keyboard\KeyboardSpeed

デフォルト値は 31 で、これは最速の繰り返し率で、1 秒あたり約 30 文字を意味します。そのため、約 1000 / 30 = 33 ミリ秒間隔を測定しました。

0 に設定した場合、つまり繰り返し速度が最も遅くなった場合、つまり 1 秒あたり約 2 文字を意味する場合、約 2 文字を測定する必要があります。500 ミリ秒間隔。この設定でコードをテストしたところ、500 ミリ秒になりました。(KeyboardSpeed を変更した後は、Windows を再起動することを忘れないでください!)

繰り返されるイベントではなく、単一のキーダウン イベントをキャッチする必要があるため、KeyboardSpeed 設定を変更する必要はありません。プログラムは、オブジェクトをユーザーに表示し、ストップウォッチを開始し、キーダウン イベントが発生した場合は停止するだけです。ElapsedMilliseconds反応時間を与えます。何度か測定して平均をとります。

問題は、QueryPerformanceCounter経過時間を正確に測定しても、キーボードと Windows 自体に起因する遅延があり、測定された反応時間が増加することです。さらに、遅延は一定ではありません。キーダウン イベントを処理する必要があるときに Windows がビジーである場合、遅延はさらに大きくなります。したがって、このタスクを真剣に受け止める場合は、プログラムを調整する必要があります。

つまり、LED をオンにし、LED をオンにしてからユーザーがボタンを押すまでの経過時間を検出する、マイクロコントローラー ベースの小さな電子デバイスを購入または構築する必要があります。このデバイスで 10 ~ 20 回 (多ければ多いほどよい) の反応時間測定を行い、同じテスト担当者で、プログラムを使用してさらに 10 ~ 20 回の測定を行います。2 つの違いは、キーボードと Windows によって引き起こされる遅延を示します。この差は、プログラムで測定された反応時間から差し引くことができます。

(Windows アプリケーションの代わりに、小さいが精密な電子デバイスを使用すべきではない理由を尋ねることができます。第 1 に、ソフトウェアの製造と販売は、ハードウェアの製造と販売よりもはるかに簡単で安価です。第 2 に、ビジュアル オブジェクトが複雑になる可能性があります (チェッカーボードなど)、複雑なオブジェクトは PC 上でより効率的にレンダリングできます)。

于 2013-10-12T23:44:09.120 に答える
1

ここで、タイミングを追跡するための別のツールを指摘したいと思います。アプリケーションの応答のテストを検討しているため、誰かが言及したように、これには OS のメッセージが関係しているため、Spy++ を使用してこれらのメッセージのタイミングを確認できます。スペースを押したときの出力を、すべての出力をオンにして、キーボード メッセージだけを聞いていたウィンドウにコピーしました。ドッキング ステーションを介した USB キーボードで、スペースを 1 回押して、できるだけ早く離しました。ダウンとアップの処理に ~.05ms かかったことがわかります。

<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++ は、Visual Studio で提供されるツールです。C:\Program Files\Microsoft Visual Studio XYZ\Common7\Tools\spyxx.exeXYZ が 8、9.0、10.0の場所で確認できます。

タイミングをさらにテストするためにできることは、Spy++ にキーボード コマンドや WM_PAINT などをリッスンさせて、UI の変更でプログラムがキーボード メッセージにどれだけ迅速に応答するかを確認することです。

たとえば、以下は Calculator を3+3既に使用してから を押した後のクリーン ログEnterです。KeyDown と KeyUp の間の処理にかかる .062ms よりも前に、電卓が計算して表示できたことがわかります。

<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)]

編集 - Spy++ では、[メッセージ オプション] ダイアログを表示する [ログ オプション] に移動することをお勧めします。[メッセージ] タブに移動し、[すべてクリア] をクリックし、[キーボード] にチェックを入れ、リストボックスをスクロールして WM_PAINT を選択します。このようにして、必要なメッセージのみを取得します。そうしないと、メッセージが殺到します。

于 2013-10-16T13:18:48.190 に答える