Windows 等待两个近同步事件的策略

Windows 等待两个近同步事件的策略,windows,multithreading,winapi,real-time,Windows,Multithreading,Winapi,Real Time,我正在编写一个库,它使用Win32 API处理击键事件。每次击键时,两个独立的事件几乎同时发生(和)。在我的库中,我有两个独立的线程,每种类型的事件(hook和raw)有一个线程 线程1(钩子)等待线程2(原始)获取数据,然后再继续。它目前使用一种类似屏障的机制来实现这一点。因此,两个事件都必须在实际处理任何一个事件之前进入。到目前为止还不错 但是(当然)有一个问题。在一个理想的世界里,我保证一直都能参加这两项活动。不幸的是,由于我不明白的原因,有时Windows决定不向我提供这两个事件中的一个

我正在编写一个库,它使用Win32 API处理击键事件。每次击键时,两个独立的事件几乎同时发生(和)。在我的库中,我有两个独立的线程,每种类型的事件(hook和raw)有一个线程

线程1(钩子)等待线程2(原始)获取数据,然后再继续。它目前使用一种类似屏障的机制来实现这一点。因此,两个事件都必须在实际处理任何一个事件之前进入。到目前为止还不错

但是(当然)有一个问题。在一个理想的世界里,我保证一直都能参加这两项活动。不幸的是,由于我不明白的原因,有时Windows决定不向我提供这两个事件中的一个(通常情况下,另一个应用程序暂时正在处理输入)。因此,如果我键入“Hello world”,线程1可能正在处理“H”,而线程2可能从未得到“H”事件,并跳到“e”。因此,事件变得不同步,所有的地狱爆发了

基本上我想要的是:我想以一种有意义的方式配对事件。如果线程1得到一个“H”事件,而线程2得到一个“e”,它应该(1)尝试等待正确的“H”事件,或者(2)超时(是的,如果必须的话,线程1可以正常失败)。因为我知道这两个事件都应该在某个时间窗口内出现,所以我认为这是一个实时编程任务

我对实时编程一无所知。是否已经有了解决方案/数据结构?如果是,它们是什么?如果不是,对于这种类型的问题,一般的方法是什么(保持两个暂时关闭的事件同步)


谢谢。

我不是win32方面的专家,但我忍不住觉得,如果您丢失了事件,在任何情况下都不会完全可靠。据我所知,您正试图根据原始物理键盘控制键盘事件的位置(即,它们指向哪个窗口)——也许最好是,而不是过滤事件,首先简单地注入它们

也就是说,只删除所有注入事件的寄存器。现在,使用原始键盘事件处理程序将模拟的WM_KEYUP/WM_KEYDOWN消息注入到最终应该接收它们的任何窗口中

但是,如果做不到这一点,我们需要(以某种方式)同步WM_输入和WM_KEY*事件流。我假设您已经了解了如何在注入的钩子DLL和“主”进程中的WM_输入侦听器之间共享数据。首先,我们将定义一个熟键流互斥体。处理WM_KEY*hook的应用程序在进行进一步处理之前会立即使用该互斥锁,以避免与其他可能也在处理密钥的进程竞争

您的WM_输入处理进程可以开始将通过WM_输入接收的键码按顺序写入共享内存环形缓冲区(由命名互斥体同步)。每个键码都应该有一个时间戳;WM_KEY*钩子将忽略旧的键代码。WM_KEY*处理程序将首先检查其事件是否与缓冲区中最早的未过期事件匹配;如果是,则应向主进程发送通知,钩子将执行所需的任何处理。没问题

如果环形缓冲区中没有数据,则可以使用命名的信号量进行睡眠。信号量的计数应该是环缓冲区中剩余条目数的乐观计数;获取计数赋予进程从缓冲区(如果存在)中取消一项的权利和义务,但如果缓冲区为空,则进程必须丢弃环互斥,并返回等待信号量。然后,钩子过程可以在其对互斥对象的等待上设置(短!)超时;如果超时过期,钩子应考虑出现故障,并进行正常处理。然后让钩子在短时间内自行禁用可能是一个好主意,以避免减慢快速键入的速度

如果钩子从环形缓冲区读取一个与它发送的击键不匹配的键码,那么在某个地方发生了失同步。这个问题的处理可能取决于你在做什么;例如,如果您正在实现一个热键系统,一种方法是简单地删除所有原始事件,并将钩子转换为纯传递,直到所有键盘在短时间内保持沉默


请记住,由于您处理的是非同步线程,每个线程都会看到多个非同步事件流的不同片段,因此去同步总是一个问题。事件注入可能仍然是避免这种情况的一种好方法,因为它提供了一个单一的同步点,可以提供事件排序。

我不是win32的专家,但我忍不住觉得,如果丢失事件,在任何情况下都不会完全可靠。据我所知,您正试图根据原始物理键盘控制键盘事件的位置(即,它们指向哪个窗口)——也许最好是,而不是过滤事件,首先简单地注入它们

也就是说,只删除所有注入事件的寄存器。现在,使用原始键盘事件处理程序将模拟的WM_KEYUP/WM_KEYDOWN消息注入到最终应该接收它们的任何窗口中

但是,如果做不到这一点,我们需要(以某种方式)同步WM_输入和WM_KEY*事件流。我假设您已经了解了如何在注入的钩子DLL和“主”进程中的WM_输入侦听器之间共享数据。首先,我们将定义一个熟键流互斥体。处理WM_KEY*hook的应用程序在进行进一步处理之前会立即使用该互斥锁,以避免与其他可能也在处理密钥的进程竞争

您的WM_输入处理进程可以开始将通过WM_输入接收的键码按顺序写入共享内存环形缓冲区(由命名互斥体同步)。每个键码都应该有一个时间戳;西医_