在信号已被触发后,Dispose()一个EventWaitHandle是否安全?

3
我有一个情况,我正在创建许多封装了每个EventWaitHandle实例的IDisposable对象,以便我的应用程序的各个感兴趣的部分可以等待它们。此实例对于其所有者对象之外的任何代码都不可直接访问。它只能通过包装器调用间接访问。
一旦对象发出信号表示已完成,它就不再有用,因此由中央管理对象处置并从其引用列表中丢弃。
现在的问题是,如何处理封装的EventWaitHandle?自然地,它也应该被处置,而且越快越好,以防止我的应用程序泄漏操作系统句柄。
但是,在事件被其所有者对象发出信号后立即同步执行这样做是否安全?如果仍有线程等待释放(即在调用WaitOne()时阻塞),会发生什么?
这里推荐采取什么方法?

当你发出信号时,你确定所有将要等待该事件的线程当前正在等待它吗?或者有些线程可能处于它们将要开始等待该事件的位置,但尚未等待它吗? - Lasse V. Karlsen
@Lasse:当然,在多线程应用程序中任何事情都可能发生。:) 但就我的对象而言,它们的WaitOne()包装器是原子的。它要么进入等待状态,要么立即返回。后者不是问题,前者是(或者至少在我看来是)。 - aoven
1个回答

1

我想现在是时候用我的发现来结束这个话题了。

我在文档中没有找到任何直接的指导方针,但决定遵循我从 Raymond Chen 的博客中提取的信息。在他的帖子中(我忘记了确切的链接),他提到 Win32 API 规则规定事件的句柄必须在等待期间保持有效。在非托管世界中,这意味着至少要保持一个事件句柄处于打开状态。

据我所知,.NET 的实现在幕后使用 Win32 API,每个 EventWaitHandle 实例对应一个单独的非托管事件。当 EventWaitHandle.Dispose() 关闭底层非托管事件的唯一句柄时,这实际上使事件实例无效。

简而言之,正确的方法似乎是建立一个平行基础设施,通过该基础设施,事件发布者可以通知潜在的侦听器事件即将很快消失。然后,发布者必须等待所有侦听器“取消订阅”(即停止等待)后,才能继续 Dispose() 事件实例。

这需要大量的簿记工作,但最终只有这样才是正确的。希望这也能帮助其他人澄清事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接