我在一些继承的 C# winforms 代码中遇到了泄漏句柄问题(“没有足够的配额来处理此命令。”),所以我使用了 Sysinternals' Handle追踪它的工具。结果发现是事件句柄泄漏了,所以我尝试用谷歌搜索它(花了几次尝试才找到一个query,但没有返回“您的意思是:事件处理程序?”)。根据Junfeng Zhang ,事件句柄是通过使用 Monitor 生成的,就事件句柄处理和同步原语而言,可能存在一些奇怪的规则。
我不完全确定泄漏句柄的来源完全是由于长生命周期对象调用大量同步内容造成的,因为此代码还处理 HID 接口(interface)和大量 win32 编码(marshal)和互操作,并且是没有进行任何我知道的同步。不管怎样,我只是要在 Windbg 中运行它并开始追踪句柄的来源,并且还花费大量时间学习这部分代码,但是我很难找到有关事件的信息句柄位于第一位。
msdn page对于事件内核对象,仅链接到通用同步概述...那么什么是事件句柄,它们与互斥体/信号量/其他有何不同?
最佳答案
NT 内核使用事件对象来允许信号传输到等待该信号的实体。互斥体和信号量也是可等待的内核对象(内核调度程序对象),但具有不同的语义。我唯一一次遇到它们是在驱动程序中等待 IO 完成时。
所以我对你的问题的理论可能是驱动程序有缺陷,或者你依赖于专门的硬件?
编辑:更多信息(来自 Windows Internals 5th Edition - 第 3 章系统机制)
一些内核调度程序对象(例如互斥体、信号量)具有概念所有权。因此,当发出释放信号时,一个等待线程将被释放,从而抢占这些资源。而其他人则必须继续等待。事件不被拥有,因此可以由任何线程重置。
还有三种类型的事件:
- 通知:收到信号后,所有等待线程都会被释放
- 同步:收到信号后,释放一个等待线程,但事件会重置
- Keyed :在信号发出时同一进程中的一个等待线程,信号发送器被释放。
我了解到的另一件有趣的事情是 critical sections ( the lock primitive in c# ) 实际上不是内核对象,而是根据需要通过键控事件、互斥锁或信号量来实现。
关于winapi - 什么是事件句柄?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2375549/