在Windows上,C#,Socket.BeginReceive()在数据到达之前还是之后采用后台线程?

在Windows上,C#,Socket.BeginReceive()在数据到达之前还是之后采用后台线程?,c#,multithreading,sockets,C#,Multithreading,Sockets,如果它在数据到达之前占用后台线程,并且当许多连接等待数据时,将存在过多线程,从而导致性能下降。有没有一种方法可以在不占用线程的情况下等待数据?Socket.BeginReceive(),以及.NET中的其他异步I/O方法都使用IOCP线程池。简短的版本是,这是一种非常有效的管理I/O的方法。等待I/O完成几乎没有成本,甚至在I/O完成后,也会从线程池线程调用完成回调,只占用该线程完成回调所需的时间 “IOCP”代表“IO完成端口”,这是本机Windows API中的一项功能。基本思想是,您可以有

如果它在数据到达之前占用后台线程,并且当许多连接等待数据时,将存在过多线程,从而导致性能下降。有没有一种方法可以在不占用线程的情况下等待数据?

Socket.BeginReceive()
,以及.NET中的其他异步I/O方法都使用IOCP线程池。简短的版本是,这是一种非常有效的管理I/O的方法。等待I/O完成几乎没有成本,甚至在I/O完成后,也会从线程池线程调用完成回调,只占用该线程完成回调所需的时间

“IOCP”代表“IO完成端口”,这是本机Windows API中的一项功能。基本思想是,您可以有一个线程,或一些线程的小集合,所有这些线程都可以为完成大量I/O操作提供服务。这使得I/O操作可以扩展到几十万(如果不是几百万的话)并发操作,同时仍然只需要相对较少的线程来处理它们

所以,请直接使用这些异步I/O API。它们是编写可伸缩I/O代码的最佳方式


(旁白:
Socket
类特别有许多异步选项。讽刺的是,以
…async
结尾的方法不符合新的(er)
异步
/
等待
C#中的范例,但实际上它们是使用
套接字
进行I/O的最具可伸缩性的方式,因为它们不仅使用IOCP线程池,还允许您重用I/O状态对象,因此您可以拥有这些对象的池并最小化GC负载。)

我并不声称自己对IO完成端口的了解超过了您在上面发布的内容,但我确信我记得在某个地方读到过,完成回调是在可以监视许多其他IO任务的同一线程上执行的,因此阻止了它们的完成。这听起来是正确的还是我弄错了?我一直认为最好将
EndReceive
的结果推送到队列中,并在线程池中处理。@Luke:这就是为什么它是一个线程池,而不仅仅是一个线程。是的,与任何线程池线程一样,您应该尽快完成操作,以便线程可以返回到池中。如果做得不对,您肯定会阻塞所有其他I/O操作。这对于任何线程池实现都是一种风险。解决办法是“不要那样做”。)也就是说,不要让线程池一直处于忙碌状态,从而耗尽线程池。这通常不需要将一个线程池操作移动到另一个线程池。因此回调是在默认的.NET线程池中的线程上执行的?@Luke:“回调是在默认的.NET线程池中的线程上执行的”——有点像。.NET
ThreadPool
类实际上管理两个线程池。使用
QueueUserWorkItem()
获得的线程池与I/O操作使用的IOCP线程池不同。但这两个都是由该类管理的。对,这很有意义,这一定是我所想的,也解释了使用
QueueUserWorkItem
从完成回调推送工作时性能的提高。谢谢你的解释。