2011-07-20 33 views
1

我有一個庫,我正在編寫使用Win32 API處理按鍵事件。每次擊鍵發生時,兩個單獨的事件幾乎同時發生(thisthis)。在我的庫中,我有兩個獨立的線程,一個用於每種事件(鉤子和原始)。等待兩個近同步事件的策略

線程1(掛鉤)等待線程2(原始)以獲取其數據,然後繼續。它目前使用類似屏障的機制來實現這一點。所以這兩個事件都必須在實際處理之前進入。到現在爲止還挺好。

但有一個問題(當然)。在一個理想的世界裏,我一定會一直得到這兩件事。不幸的是,由於我不明白的原因,有時Windows決定不向我發送其中一個事件(通常是另一個應用程序暫時與輸入有關)。因此,如果我輸入「Hello world」,線程1可能正在處理「H」,而線程2可能從未得到「H」事件並跳到「e」。所以這些事件不同步,所有的事情都打破了。

基本上我想是這樣的:我要配對的事件在某種程度上是有道理的。如果線程1得到一個「H」事件,並且線程2得到一個「e」,它應該或者(1)嘗試等待正確的「H」事件,或者(2)超時(是的,線程1可以優雅地失敗如果必須的話)。既然我知道這些事件都應該在一定的時間窗口內進入,我想這使得這是一個實時編程任務。

我對實時編程一無所知。是否已有解決方案/數據結構?如果是這樣,他們是什麼?如果不是,這種類型的問題的一般方法是什麼(保持兩個時間上緊密的事件同步)?

謝謝。

+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和WM_INPUT監聽器之間共享數據。我們將通過定義熟鍵密鑰流互斥開始。處理WM_KEY *鉤子的應用程序會在進行進一步處理之前立即使用該互斥鎖,以避免與可能也是處理鍵的其他進程競爭。

你WM_INPUT處理過程可以開始寫入,以便接收到WM_INPUT的鍵碼的共享存儲器環緩衝液(由名爲互斥同步)。每個鍵碼應該有一個時間戳; WM_KEY *鉤子將忽略舊的鍵碼。 WM_KEY *處理程序將首先檢查它們的事件是否匹配緩衝區中最早的未到期事件;如果是,則通知應發送到主進程,並且掛鉤將執行所需的任何處理。沒問題。

如果在環形緩衝器中沒有數據,命名信號量可用於睡覺。信號量的計數應該是環形緩衝區中剩餘條目數的樂觀計數;獲得一個計數給了一個進程有權利和義務從緩衝區取出一個項目(如果存在的話),但是如果緩衝區是空的,進程必須丟棄環互斥並返回等待信號量。然後鉤子程序可以在其等待互斥體時發出(短暫的!)超時;如果超時到期,掛鉤應認爲已經進行了異步,並繼續進行正常處理。爲了避免減慢快速鍵入,可以讓鉤子在短時間內禁用自己,這可能是一個好主意。

如果掛鉤從環形緩衝區中讀取與其發送的鍵擊不匹配的鍵碼,則在某處發生了異步。處理這可能取決於你在做什麼;例如,如果您正在實施熱鍵系統,則一種方法是簡單地刪除所有原始事件,然後將鉤子轉換爲純傳遞,直到所有鍵盤在很短的時間間隔內保持沉默。請記住,由於您正在處理未同步的線程,每個線程都會看到多個不同步的事件流的不同切片,因此desyncs始終會成爲問題。事件注入可能仍然是一種避免這種情況的好方法,因爲它爲您提供了一個可以提供事件排序的同步點。

+0

在這一點上,我不一定非常「完全可靠」,而是「最終一致」。 –

+0

考慮一下:用戶輸入「aaba」。原始輸入處理程序中丟失了中間的「ab」。所以你看到「aaba」的WM_KEY *事件,而「aa」的WM_INPUT事件。你將這些與這個詞的開始匹配起來。現在用戶鍵入「香蕉」,事情變得更加困惑。由於信息沒有序列號,如果你失去了事件,你將會感到困惑。我想問題是這種混亂可能有多嚴重。 – bdonlan

+0

噢相信我,我已經很困惑了:)沒有問題的關鍵是:我知道這兩個事件都應該在一定時間內進入系統。我能以某種方式利用這一點,並將事件過濾爲時間上最接近的事件嗎? –