因为听起来你从 asio 获得的主要用途是它建立在 IO 完成端口(简称 iocp)之上。所以,让我们从比较 iocp 和WaitForMultipleObjects()
. 这两种方法与linux 上的select
vs.基本相同。epoll
iocp 解决的主要缺点WaitForMultipleObjects
是无法使用许多文件描述符进行扩展。它是 O(n),因为对于您收到的每个事件,您都会再次传入完整的数组,并且内部 WaitForMultipleObjects 必须扫描数组以了解要触发哪些句柄。
然而,由于第二个缺点,这很少成为问题。WaitForMultipleObjects()
它可以等待的最大句柄数有限制 ( MAXIMUM_WAIT_OBJECTS
)。此限制为 64 个对象(请参阅 winnt.h)。有一些方法可以绕过这个限制,方法是创建 Event 对象并将多个套接字绑定到每个事件,然后等待 64 个事件。
第三个缺点是WaitForMultipleObjects()
. 它返回触发事件的句柄的索引。这意味着它只能将单个事件传回给用户。这与 不同select
,后者将返回触发事件的所有文件描述符。WaitForMultipleObjects
扫描传递给它的句柄并返回第一个引发其事件的句柄。
这意味着,如果您正在等待 10 个非常活跃的套接字,并且大部分时间所有这些套接字上都有一个事件,那么将非常倾向于为传递给的列表中的第一个套接字提供服务WaitForMultipleObjects
。这可以通过以下方式规避:每次函数返回并且事件已得到服务时,以 0 的超时时间再次运行它,但这次仅传递数组 1 中触发事件之后的部分。重复直到所有句柄都被访问,然后返回到所有句柄和实际超时的原始调用。
iocp 解决了所有这些问题,并且还引入了一个更通用的事件通知接口,这非常好。
使用 iocp(因此也是 asio):
- 你不重复你感兴趣的句柄,你告诉windows一次,它就会记住它。这意味着它可以通过许多句柄更好地扩展。
- 您可以等待的句柄数量没有限制
- 你得到每一个事件,即没有对任何特定句柄的偏见
我不确定您是否假设async_read
在自定义句柄上使用。你可能需要测试一下。如果您的句柄指的是套接字,我想它会起作用。
至于线程问题;是的。如果您run()
在io_service
多个线程中,事件将被分派到一个空闲线程,并将随着更多线程进行扩展。这是 iocp 的一个特性,它甚至还有一个线程池 API。
简而言之:我相信 asio 或 iocp 会提供比简单地使用更好的性能WaitForMultipleObjects
,但是这种性能是否对您有利主要取决于您拥有多少句柄以及它们的活跃程度。