为什么是eventwaihandle.WaitAny方法有64个句柄限制
本文关键字:64个 句柄 方法 eventwaihandle WaitAny 为什么 | 更新日期: 2023-09-27 18:14:27
我有一个应用程序,它需要控制许多从属进程来完成任务。有一个匹配线程来做匹配工作。我使用EventWaitHandle在它们之间进行通信,在空闲时间匹配线程等待slave的事件,代码如下:
EventWaitHandle.WaitAny(GetWaitEvents());
//GetWaitEvents method will return all slave process's EventWaitHandle
在从进程中,一旦空闲。它将触发事件以将另一个任务匹配到此流程。代码:
ProxyEvent.Set()
但是,当事件数超过64时,它将抛出System.NotSupportedException。在检查了从微软获得的代码后,我发现它是框架代码中的硬代码:
private const int MAX_WAITHANDLES = 64;
我的问题是:
- 为什么有这样的限制?为什么是64年?
- 有解决这个限制的方法吗?
Why?很容易回答,只要你意识到它是从WaitForMultipleObjects
遗传的。反过来,它也有一个限制,因为函数的返回值试图将多个事实编码成一个整数,所以他们选择了一个应该适应大多数情况的实用值。
我同意@Pako的评论-很可能运行(超过)64个线程可能不是最好的方法-如果它们都是活动的,而你的内核少于64个,你可能会淹没系统,并且当它可以执行有用的工作时,它会浪费时间执行上下文切换。
使用例如Task
s或TPL将允许您的代码根据实际执行的工作量优雅地扩展。
64的原因是64是64位处理器上一个字的位数。
实现使用位标志使其尽可能快。
变通方法根据您尝试做的事情而有所不同。参见示例WaitHandle的解决方法。WaitAll 64句柄限制?正如V4Vendetta所提到的。
我使用的一种解决方法是将等待句柄拆分为两个数组,然后使用一个线程等待其中一个数组,另一个线程等待另一个数组。然后主线程等待这两个线程中的任何一个。这不是很好,因为它使用了一个额外的线程。(我对它的实际实现比上面的解释所暗示的要复杂得多。我必须将每个数组中的等待句柄的数量限制为63个,因为我需要额外的一个来停止"其他"句柄。当其中一个线程完成对数组的等待时,线程正在等待。)
WaitForMultipleObjects()
的MSDN文档确实提到了几个解决方案:
创建一个线程来等待MAXIMUM_WAIT_OBJECTS句柄,然后等待该线程和其他句柄。使用此技术将句柄分解为MAXIMUM_WAIT_OBJECTS组。
调用RegisterWaitForSingleObject等待每个句柄。来自线程池的等待线程等待MAXIMUM_WAIT_OBJECTS注册对象,并在对象发出信号或超时时间过期后分配一个工作线程。
(我过去使用第一种方法,但我早就重写了该代码,改为使用IO完成端口)