2011-07-20 9 views
1

私は、Win32 APIを使用してキーストロークイベントを処理するライブラリを用意しています。キーストロークが発生するたびに、2つの別々のイベントがほぼ同時に発生します(thisthis)。私の図書館では、2種類のスレッドがあります。それぞれの種類のイベント(フックとロー)に1つずつあります。2つのほぼ同期イベントを待つための戦略

スレッド1(フック)は、スレッド2(未加工)を待ってからデータを取得します。現在、これを達成するために障壁のような仕組みが使用されています。どちらのイベントも実際に処理される前に両方のイベントが来なければなりません。ここまでは順調ですね。

しかし、問題があります(もちろん)。理想的な世界では、私はいつも両方のイベントを取得することが保証されます。残念ながら私が理解していない理由から、Windowsは2つのイベントのうちの1つを私に渡すことを決してしないことがあります(しばしば、別のアプリが一時的に入力に悩まされている)。そして、もし私が "Hello world"とタイプすると、スレッド1は "H"を処理しているかもしれないし、スレッド2は "H"イベントを得たことがなく、 "e"にスキップしているかもしれません。イベントが同期しなくなり、すべての地獄が緩んでしまいます。

基本的に私はこれを望んでいます。私はイベントを意味のある方法でペアにしたいと思っています。スレッド1が "H"イベントを取得し、スレッド2が "e"を取得した場合、(1)正しい "H"イベントを待つか、(2)タイムアウトするか(はい、スレッド1は正常に失敗する可能性がありますそれが必要ならば)。イベントはどちらも一定の時間枠内に入ってくるはずなので、これがリアルタイムプログラミングの仕事になると思います。

私はリアルタイムプログラミングについては何も知りません。これにはすでにソリューション/データ構造がありますか?もしそうなら、彼らは何ですか?もしそうでなければ、このタイプの問題に対しては一般的なアプローチは何でしょうか(時間的に近い2つのイベントを同期させておくこと)?

ありがとうございました。

+0

なぜ両方を待っていますか? – bdonlan

+1

APIを使用すると、キーストロークがどこで行われるかを制御できます。私は両方のことを行う能力が必要です(どのキーボードがそれを送信したかによって入力がどこになるかを制御します)。これはちょうどこのマッチングアップイベントで、今は恐ろしい頭痛です。 –

+0

確かに、WM_KEYUP/WM_KEYDOWNメッセージは、入力フォーカスのあるウィンドウに移動するだけです... ...? – bdonlan

答えて

1

私はwin32の専門家ではありませんが、イベントを失っても完全に信頼できるものはありません。私が理解しているように、起源の物理キーボードに基づいてキーボードイベントがどこに行くか(つまりどのウィンドウに行くか)を制御しようとしています。イベントをフィルタリングする代わりに、場所。

つまり、登録されたすべてのイベントを単に廃棄するlow-level keyboard hookを登録します。今すぐ生キーボードのイベントハンドラを使用して、エミュレートされたWM_KEYUP/WM_KEYDOWNメッセージを最後に受け取るウィンドウに挿入します。

しかし、私たちは(何らかの形で)WM_INPUTとWM_KEY *イベントストリームを同期させる必要があります。注入されたフックDLLと 'master'プロセスのWM_INPUTリスナの間でデータを共有する方法については、すでに説明しています。 cooked-keystream mutexを定義することから始めます。 WM_KEY *フックを処理するアプリケーションは、キーを処理している可能性のある他のプロセスとの競合を避けるために、この処理を行う前に直ちにこのミューテックスを使用します。

WM_INPUT処理プロセスは、WM_INPUTで受信したキーコードを順番に共有メモリリングバッファ(名前付きミューテックスで同期)に書き込むことができます。各キーコードにはタイムスタンプが必要です。 WM_KEY * hooksは古いキーコードを無視します。 WM_KEY *ハンドラは、まずそのイベントがバッファ内の最も古い有効期限のないイベントと一致するかどうかをチェックします。そうであれば、通知がマスタプロセスに送信され、フックはどのような処理が必要なものであれ、それを行う。問題ない。

リングバッファにデータがない場合、名前付きセマフォを使用してスリープすることができます。セマフォのカウントは、リングバッファに残っているエントリの数を楽観的にカウントする必要があります。カウントを取得すると、プロセスにバッファからアイテムを取り出す権利と義務が与えられますが、バッファが空の場合、プロセスはリングミューテックスを落としてセマフォを待機する必要があります。フックプロシージャは、ミューテックスの待機時間に(短い!)タイムアウトを置くことができます。タイムアウトが切れると、フックはそこにデシンクがあるとみなし、通常の処理を続行します。速いタイピングを遅らせるのを避けるために、短い間隔でフックを無効にすることをお勧めします。

フックは、それが、その後、どこかDESYNCがあった送られたキーストロークと一致しないキーコードをバッファリングから読み取る場合。これの処理は、あなたがやっていることに依存するかもしれません。たとえば、ホットキーシステムを実装している場合、すべての未処理イベントをドロップし、短い間隔ですべてのキーボードが無音になるまで、フックを純粋なパススルーに変えます。

あなたが非同期スレッドを扱っていることから、それぞれが複数の、非同期のイベントストリームの異なるスライスを見て、心に留めておいてください、desyncsは常に問題となります。これを回避するには、イベントの順序付けを行うことができる単一の同期ポイントが与えられるため、イベント注入はまだこれを避けるための良い方法です。

+0

この時点では、必ずしも「完全に信頼できる」とは言えません。 –

+0

これを考慮してください:ユーザーは "aaba"と入力します。途中の "ab"は生の入力ハンドラで失われます。したがって、 "aaba"のWM_KEY *イベントは表示されますが、 "aa"のWM_INPUTイベントが表示されます。これらを単語の先頭に合わせます。ユーザーは「バナナ」と入力すると、物事はさらに混乱します。メッセージにはシーケンス番号がないので、イベントを失うと、_あなたは混乱します。私はこの混乱がいかに有害であるかという疑問を持っていると思います。 – bdonlan

+0

ああ私を信じて、私は十分混乱している:)問題の要点はこれではない:私は、両方のイベントがお互いに一定の時間内にシステムに来るはずであることを知っている。私は何とかこれを利用して、時間的に最も近いイベントにフィルタイベントを適用できますか? –

関連する問題