使用.NET的异步套接字似乎存在线程池问题

时间:2014-09-12 06:16:39

标签: .net multithreading sockets threadpool asyncsocket

我注意到下面链接的异步套接字发送和接收形式MSDN的示例不起作用。发生的事情是,使用BeginReceive在Receive中创建的线程不会启动,直到在方法StartClient上运行的线程退出该方法。因此,receiveDone.WaitOne()事件从不被调用,因为接收方法中的信号器永远不会被命中,因为beginReceive创建的工作线程在StartClient方法返回之前不会启动。

我也在网上看到了很多关于这个问题的引用。

有没有人对这个问题有一些想法?

http://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx

1 个答案:

答案 0 :(得分:2)

要获得完整的示例,您需要构建服务器和客户端,并同时运行它们。服务器示例中的Send用于向客户端的请求发送响应

BeginSend(以及其他BeginXXX方法)立即启动异步I / O请求 - 它不需要任何线程。一旦I / O请求在线程池上的I / O线程上完成(由NIC的物理硬件部分处理,部分由内核处理),就会运行回调。因此,示例客户端使用异步I / O编写,但在其他方面几乎是同步的。在这种情况下,sendDone.WaitOne();完全没必要,但它也不会受到伤害。

.NET的异步套接字使用IOCP,而不是多线程。基本思想是你有一些I / O线程,用于处理异步I / O"推送"来自操作系统。异步I / O本身并不需要线程池中的任何线程,否则,您只需要一个回调线程(在这种情况下,AcceptCallbackReadCallback和类似的方法)。

在任何情况下,这都是过时的样本,并且与所有样本一样,您不应该开箱即用。它几乎是您可以构建的最简单的异步套接字服务器。事实上,这是一个更好的示例 - 它正确处理套接字关闭,正确读取数据,甚至处理原始消息框架(<EOF>)。

为了更详细地解释一下样本,还有一些事情正在同时进行。

服务器中的主线程只做一件事 - 反复启动异步I / O&#34;请求&#34;接受传入的TCP连接。等待句柄用于避免不必要的轮询/循环 - 您可以在执行BeginAccept(异步I / O请求以接受连接)之前看到它已重置,并在回调中设置({{1} }) - 这将允许主线程再次循环并接受 new 连接。

AcceptCallback也会启动异步I / O请求,这次是接收数据。当网络接口接收给定套接字的数据时,数据将保存到DMA缓冲区,并将回调发布到线程池I / O线程。这是AcceptCallback方法执行的地方。

所以,正如你所看到的,如果没有请求,除了主线程之外没有线程(这并不重要,因为退出主线程会终止应用程序)。只有当回调到来时,才会从I / O池中获取一个线程,并且一旦回调完成(几乎立即),就会返回。