2011-03-15 81 views
2

我有一种情况,我创建了多个IDisposable对象,每个对象封装了一个EventWaitHandle实例,以便我的应用程序的各个感兴趣部分可以在其上等待。该实例不能直接访问其所有者对象外的任何代码。它只能通过包装调用间接访问。在发送信号后处理()EventWaitHandle是否安全?

一旦对象发出信号,它就不再有用,因此它由中央管理器对象处理并从其参考列表中抛弃。

现在的问题是,如何处理封装的EventWaitHandle?当然,它也应该被处置,并且尽快,以防止我的应用程序泄漏操作系统句柄。

但是,在事件通过其拥有者对象发出信号后立即同步执行该操作是否安全?如果还有线程仍在等待释放(即阻塞在WaitOne()的呼叫中),会发生什么情况?

这里推荐的方法是什么?

+0

你确定当你发出信号时* *会等待事件的所有线程是*当前*等待它吗?或者有些线程可能在他们开始等待事件之前处于某个位置,但还没有等待呢? – 2011-03-15 11:34:08

+0

@Lasse:好吧,当然,在多线程应用程序中可能会发生任何事情。 :)但就我的对象而言,它们的WaitOne()包装器是原子的。它要么进入等待,要么立即返回。后者不是问题,前者是(或者至少可以是,在我看来)。 – aoven 2011-03-15 11:44:11

回答

0

我想是时候用我自己的发现来结束这一次。

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

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

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

这是很多簿记,但最终,它似乎只是正确的。希望这有助于为其他人清除一些事情。