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

.net NET的异步套接字似乎在线程池中存在问题,.net,multithreading,sockets,threadpool,asyncsocket,.net,Multithreading,Sockets,Threadpool,Asyncsocket,我注意到下面链接的异步套接字发送和接收表单MSDN的示例不起作用。发生的情况是,在Receive中创建的带有BeginReceive的线程在方法StartClient上运行的线程退出该方法之前不会启动。因此,永远不会调用receiveDone.WaitOne事件,因为Receive方法中的信号器永远不会被命中,因为在方法StartClient返回之前,beginReceive创建的工作线程不会启动 我也在网上看到很多关于这个问题的参考资料 有人对这个问题有什么想法吗 要获得完整的示例,您需要同时

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

我也在网上看到很多关于这个问题的参考资料

有人对这个问题有什么想法吗


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

BeginSend和其他BeginXXX方法立即启动异步I/O请求-它不需要任何线程。I/O请求完成后,回调将立即运行,该请求部分由NIC的物理硬件处理,部分由内核在线程池的I/O线程上处理。因此,示例客户机是使用异步I/O编写的,但在其他方面几乎是同步的。sendDone.WaitOne;在这种情况下是完全没有必要的,但也没有什么坏处

.NET的异步套接字使用IOCP,而不是多线程。基本思想是,您有两个I/O线程,用于处理来自操作系统的异步I/O推送。异步I/O本身不需要线程池中的任何线程,在本例中,回调只需要一个线程,即AcceptCallback、ReadCallback和类似的方法

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

为了更详细地解释这个示例,同时还有一些事情正在进行

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

AcceptCallback还启动一个异步I/O请求,这次是为了接收数据。当网络接口接收到给定套接字的数据时,数据被保存到DMA缓冲区中,回调被发送到线程池I/O线程。这就是ReadCallback方法执行的地方


因此,正如您所看到的,如果没有请求,那么除了主线程之外就没有线程,这其实并不重要,因为退出主线程将终止应用程序。只有在回调到来时,才会从I/O池中提取一个线程,并且在回调几乎立即完成时返回。

我不理解这个问题,我以为这是在异步套接字中……为什么它被标记为ThreadPool?它将在调用BeginReceive的方法完成后很长很长时间内开始运行。网络连接比处理器慢得多。如果使用调试器,时间甚至更长。这正是异步套接字的要点,您永远不想等待它。如果回调从未运行,则说明您做错了。可能是试图连接到一台没有响应或被防火墙阻止的机器。@Aron:我用ThreadPool标记了这个问题,因为我无法解释这个行为,这就像ThreadPool耗尽了线程,在线程可用之前不允许启动beginReceive。不过,情况很可能并非如此,因为在进行此调用时,只使用了大约8个线程。@Hans:谢谢您的评论,不过这是针对我14年前编写的服务器的,该服务器正在生产中运行,没有任何问题。唯一的问题是,在更新客户端应用程序时,我决定使用.NET异步方法,并且遇到了这个问题。具体的问题是,在这个来自MS的示例中,beginRead在方法startClient返回之前不会调用AsyncCallback,无论我在调试器中等待多长时间。这就像AsyncCallback线程被加入到运行startClient方法的线程中一样。@karlasterly这是在MSDN中完全相同的代码中发生的,两者都在单独的控制台应用程序中吗?另外,请注意,该示例缺少对同步完成的操作的检查-如果从BeginXXX返回的IAsyncResult已同步完成设置,则不会调用回调-您必须自己调用它。这是相当有趣的
不太可能在网络上发生,但如果您在本地主机上进行测试,可能会发生这种情况,尤其是在涉及所有等待的情况下。谢谢您的评论。我理解你对IOCP的评论,但我不知道。我也明白,我不应该开箱即用,我只是在做提供的样本的初始原型,以获得概念证明。我面临的关键问题是beginReceive是一个异步方法调用。它应该独立于调用beginReceive的线程的状态来调用回调方法。发生的情况是,asyncCallback的行为就好像它是一个连接到startClient方法中运行的线程的线程。我很困惑。。。