我通过 ManualResetEvent 创建了一个跨进程事件。当此事件确实发生时,n 个不同进程中的 n 个线程应该被解除阻塞并开始运行以获取新数据。问题在于,ManualResetEvent.Set 之后立即重置似乎不会导致所有等待线程唤醒。那里的文档很模糊
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
当手动重置事件对象的状态发出信号时,它会一直保持信号状态,直到它被 ResetEvent 函数显式重置为非信号状态。任何数量的等待线程,或随后开始等待指定事件对象的线程,都可以在对象状态发出信号时被释放。
有一种名为PulseEvent的方法似乎完全符合我的需要,但不幸的是它也有缺陷。
等待同步对象的线程可以通过内核模式 APC 暂时从等待状态中移除,然后在 APC 完成后返回等待状态。如果对 PulseEvent 的调用发生在线程已从等待状态中移除的时间内,则不会释放线程,因为 PulseEvent 仅释放在调用它时正在等待的那些线程。因此,PulseEvent 是不可靠的,不应被新应用程序使用。相反,使用条件变量。
现在 MS 确实建议使用条件变量。
条件变量是同步原语,使线程能够等待特定条件发生。条件变量是不能跨进程共享的用户模式对象。
按照文档,我似乎没有运气可靠地做到这一点。是否有一种简单的方法可以在没有规定限制的情况下通过一个 ManualResetEvent 完成相同的事情,或者我是否需要为每个侦听器进程创建一个响应事件以获取每个订阅调用者的 ACK?在这种情况下,我需要一个小的共享内存来注册订阅进程的 pid,但这似乎带来了自己的一系列问题。当一个进程崩溃或没有响应时会发生什么?……
给出一些上下文。我有新的状态要发布,所有其他进程都应该从共享内存位置读取。当一次发生多个更新时,错过一个更新是可以的,但该过程必须至少读取最后一个最新值。我可以用超时进行轮询,但这似乎不是一个正确的解决方案。
目前我已经到
ChangeEvent = new EventWaitHandle(false, EventResetMode.ManualReset, counterName + "_Event");
ChangeEvent.Set();
Thread.Sleep(1); // increase odds to release all waiters
ChangeEvent.Reset();