这样怎么不导致栈溢出呢?我正在查看使用SocketAsyncEventArgs的服务器的源代码,并且我试图弄清楚这不会导致堆栈溢出:因此调用此代码以允许套接字接受传入连接(向下滚动到下面看看我的意思)://////开始一个操作来接受来自客户端的连接请求。//////在服务器的侦听套接字上发出///接受操作时使用的上下文对象。privatevoidStartAccept(SocketAsyncEventArgsacceptEventArg){if(acceptEventArg==null){acceptEventArg=newSocketAsyncEventArgs();acceptEventArg.Completed+=newEventHandler(OnAcceptCompleted);}else{//必须清除套接字,因为上下文对象正在被重用。acceptEventArgocket}=接受;this.semaphoreAcceptedClients.WaitOne();布尔willRaiseEvent=this.listenSocket.AcceptAsync(acceptEventArg);如果(!willRaiseEvent){this.ProcessAccept(acceptEventArg);}}然后在连接被真正接受后调用这段代码(见最后一行)://////为套接字监听器处理接受。//////与完成的接受操作关联的SocketAsyncEventArg配给。privatevoidProcessAccept(SocketAsyncEventArgse){if(e.BytesTransferred>0){Interlocked.Increment(refthis.numConnectedSockets);Console.WriteLine("已接受客户端连接。有{0}个客户端连接到服务器",this.numConnectedSockets);}//获取接受的客户端连接的套接字并将其放入//ReadEventArg对象用户令牌。SocketAsyncEventArgsreadEventArgs=this.readWritePool.Pop();readEventArgs.UserToken=e.AcceptSocket;//客户端连接后,立即向连接发送接收消息。布尔willRaiseEvent=e.AcceptSocket.ReceiveAsync(readEventArgs);如果(!willRaiseEvent){this.ProcessReceive(readEventArgs);}//接受下一个连接请求。这。开始接受(e);//<====尾端递归?}查看最后一行它再次调用顶层函数。通过在这两个函数之间来回ping-ponging,这如何不溢出堆栈?它似乎是尾递归的,但这不是Haskell,所以我不知道它是如何工作的。我的理解是,这些不是在线程中触发的,而是由cpu一次一个执行的。如果不能立即满足AsyncAccept(或任何AsyncXXX操作),则它将返回true,表示操作将异步完成。发生这种情况时,回调事件最终会在线程池线程上触发。即使它编组回UI线程(因为它是在那里启动的),它也会通过post完成。AsyncAccept很可能会返回true,因为您正在等待客户端连接,除非有一个真正的套接字连接挂起(请参阅Listen中的积压)。因此StartAccept()将在不调用ProcessAccept的情况下退出,并且ProcessAccept可能在(如果)它触发时位于不同的线程上。看一下代码:if(!willRaiseEvent){this.ProcessAccept(acceptEventArg);}虽然我没看懂整个机制,willRaiseEvent==true肯定是结束了递归,所以我猜测会出现这种情况,所以不是NoneRestless递归。这完全取决于willCauseEvent标志,当它设置为true时会中断递归。如果没有挂起的连接,则此标志可以设置为true。很难从上下文中分辨出来,但看起来像第一个直接调用第二个时BooleanwillRaiseEvent=this.listenSocket.AcceptAsync(acceptEventArg);if(!willRaiseEvent){所以我想大多数时候它会在完成事件(来自不同的回调线程)时引发?(另请参阅“堆栈潜水”部分http://blogs.msdn.com/mjm/archive/2005/05/04/414793.aspx这似乎是类似的事情。)ProcessAccept()总是调用StartAccept()但反之则不然。在StartAccept()中,仅当willRaiseEvent设置为true时才会调用ProcessAccept()。那就是你从那里的无限递归出口。如果您怀疑无限递归,您总是会寻找可能的出口点(在递归函数或您的乒乓函数之一中,正如您雄辩地说的那样:-)。以上就是C#学习教程:这样怎么能不引起栈溢出呢?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
