windows - 关于 Win32 ##Event## 同步对象的问题

标签 windows winapi

先介绍一下应用场景:

我有一个服务应用程序正在监视某物的状态,同时还有多个应用程序正在等待状态更改。一旦状态发生变化,每个应用程序将读取状态值(通过命名的 FileMap 对象)并执行相应的操作,然后等待状态再次发生变化。

所以我使用了一个命名的事件对象来做同步工作。所有应用程序都在等待此事件被发出信号,并且服务应用程序将设置此事件以在该状态更改时被发出信号。

我需要保证当状态改变时,每个等待的申请都会被释放并且只被释放一次!

这两种方法我都试过了

方法一

  1. 创建手动重置事件;
  2. 当状态改变时,先调用SetEvent,然后立即调用ResetEvent。

方法二

  1. 创建手动重置事件;
  2. 当状态改变时,调用 PulseEvent。

这两种方法在测试过程中似乎都很有效。但我认为它们都不可靠,因为:

对于##方法1 ##,在调用ResetEvent函数之前,可能一些等待线程没有机会执行。

对于##方法2##,微软声称PulseEvent is unreliable and should not be used .

这个案例有什么可行的解决方案吗?欢迎任何建议。

最佳答案

无法使用 O(1) 同步原语安全地实现这一点。

要通知 N 个应用程序有关新的状态更改,请使用 N 个事件。服务应设置它们,每个应用程序应在处理当前状态更改时重置其相应的事件。

要等待所有应用程序处理新的状态更改服务,可以使用另一组 N 个事件和带有 bWaitAll==TRUE 的 WaitForMultipleObjects。每个应用程序都应该设置它对应的事件。

因此,服务执行一个循环:观察状态变化,写入共享内存,设置所有 A 事件,等待所有 B 事件,重置所有 B 事件,继续循环。每个应用程序都执行一个循环:WAITING其 A(i) 事件、重置 A(i)、处理状态更改、设置 B(i)、继续循环。

A事件和B事件都可以是自动复位类型。然后您无需重置任何内容。

如果您觉得环保并且不想浪费资源,您可以使用某种反向信号量来代替 B 组事件。这可以通过一个由互斥量同步的共享计数器和一个通知服务的事件 (B') 来实现。服务不会等待整个 B 集,而是等待 B',当等待结束时将计数器设置为 N。每个应用程序不应设置其 B(i) 事件,而是应递减计数器,如果计数器降为零,则最后一个应用程序应仅设置 B'。

您无法绕过 A 组事件。问题不在于设置 A 事件,而在于重置。通过重置其 A(i) 事件,应用程序将不会错过另一个状态更改。并且在这里使用信号量也没有帮助。

请注意,此解决方案未考虑应用程序可能崩溃的情况。如果发生这种情况,该服务将永远等待不存在的应用程序响应。

关于windows - 关于 Win32 ##Event## 同步对象的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4322193/

相关文章:

c# - 将 "chained process"固定到任务栏

windows - Windows 防病毒软件如何与文件访问过程 Hook ?

python - 使用 gitbash 终端将文件从 Windows 10 移动到 ubuntu 文件夹

asp.net-mvc - 使用 IIS 的 MVC "Access is Denied"

windows - 适用于 Windows 的 VIM : How to edit to the end of line but before EOL character

c - 如何使用 GetFullPathName 提取没有文件夹路径的文件名

c++ - 使用 GetKeyState()

C# Azure MediaServices 上传文件引发错误

c++ - 使用 EvtSetChannelConfigProperty() 函数时出现访问冲突错误

c# - 如何通过 Ctrl+Shift+d 使用 registerHotKeys 函数