什么是Win32 PulseEvent()函数的替代品?

Bil*_*ill 8 winapi synchronization ipc

Win32 API PulseEvent()函数(kernel32.dll)的文档声明此函数"......不可靠,不应被新应用程序使用.相反,使用条件变量".但是,条件变量不能像(命名)事件那样跨进程边界使用.

我有一个跨进程,跨运行时(本机和托管代码)的场景,其中单个生产者偶尔会有一些有趣的东西让或更多的消费者知道.现在,生产者使用此PulseEvent函数使用一个众所周知的命名事件(并设置为信号状态),当它需要知道某些事情时.零个或多个消费者等待该事件(WaitForSingleObject())并在响应中执行操作.在我的场景中不需要双向通信,并且生产者不需要知道事件是否有任何监听器,也不需要知道如果该事件是在成功地采取行动.另一方面,我不希望任何消费者曾经错过任何事件.换句话说,系统需要是完全可靠的-但是生产者并不需要知道,如果是这样的话该场景可以被认为是"时钟自动收报机" - 即,生产者为零个或多个消费者提供半常规信号以供计数.并且所有消费者必须在任何给定的时间段内具有正确的计数.允许消费者进行轮询(表现原因).自动收报机只有几毫秒(20左右,但并非完全正常).

Raymen Chen(The Old New Thing)有一篇博客文章指出了PulseEvent()函数的"根本缺陷"性质,但是我没有看到陈的陈述或发布的评论的替代方案.

任何人都可以建议吗?

请记住,IPC信号必须跨越机器上的处理边界,而不仅仅是线程.解决方案需要具有高性能,因为消费者必须能够在每个事件的10ms内采取行动.

Len*_*ate 6

我认为你需要一些更复杂的东西来达到你的可靠性目标.

我对你的问题的理解是你有一个生产者和一个未知数量的消费者,所有这些消费者都是不同的过程.每个消费者都不会错过任何活动.

我想更多地澄清一个事件的缺失意味着什么.

i)如果一个消费者开始运行并且在它等待你的通知方法之前就已经发生并且发生了一个事件它是否应该处理它,即使它在发送通知时尚未准备就绪?(即,当消费者被认为是活跃的?什么时候开始或者它处理第一个事件时)

ii)同样,如果消费者正在处理事件并且等待下一个通知的代码尚未开始等待(我假设Wait -> Process -> Loop to Wait代码结构)那么它应该知道在循环时发生了另一个事件吗?

我认为i)是"不是真的",因为它是一个过程启动和"准备好"之间的竞赛,而ii)是"是"; 一旦消费者出现,每个消费者都会消费所有在活动时产生的事件并且不会跳过任何事件,那么通知就会有效地排队.

因此,您所追求的是能够向一组消费者发送通知流,其中消费者可以保证对该流中的所有通知采取行动,从其作用于第一个到关闭的点. .即如果生产者产生以下通知流

1 2 3 4 5 6 7 8 9 0

和消费者a)启动和处理3,它也应该处理4-0

如果消费者b)启动并处理5但在9之后关闭则应该处理5,6,7,8,9

如果消费者c)在通知开始时正在运行它应该已经处理1-0

等等

简单地说一个事件不会起作用.如果消费者在事件发生脉冲时没有主动等待事件,那么它将错过事件,因此如果事件的产生速度快于我们可以循环再次等待事件,我们将失败.

使用旗语也不会工作,就好像一个消费者的运行速度比其他消费者更快到这样的程度,它可以循环绕到信号呼叫其他完成处理,如果有那个时间内另一个通知则一个消费者可以处理一个事件比以前多了一次,一次可能错过一次.那就是你可能会释​​放3个线程(如果生产者知道有3个消费者),但你不能确保每个消费者只被释放一次.

共享内存中的事件(滴答计数)的环形缓冲区,每个消费者知道它上次处理的事件的价值以及通过脉冲事件向消费者发出警报,应该以牺牲一些消费者与蜱不同步为代价; 也就是说,如果他们错过了一个,他们会在下次发出脉冲时赶上.只要环形缓冲区足够大,以便所有消费者可以在生产者在缓冲区中循环之前处理事件,您应该没问题.

通过上面的例子,如果消费者d错过了事件4的脉冲,因为它当时没有等待它的事件,然后它进入等待状态,它将在事件5产生时被唤醒,并且因为它的最后处理计数是3它将处理4和5,然后循环回到事件......

如果这还不够好,那么我建议像PGM一样通过套接字给你一个可靠的组播; 这样做的好处是你可以将你的消费者转移到不同的机器上......