【发布时间】:2013-05-06 06:35:17
【问题描述】:
我通过 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 是不可靠的,不应该被 new 应用程序。而是使用条件变量。
现在 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();
【问题讨论】:
标签: c# .net windows multithreading